/** \file NXPoint.h * \brief Implements point-vector classes using expression templates */ #ifndef NX_POINT_H #define NX_POINT_H #include #include "Nanorex/Utility/NXUtility.h" namespace Nanorex { template class NXPointRef; template class NXPoint; static double const NX_DEFAULTTOL = 1.0e-6; /* CLASS: NXPointRef */ /** * N-dimensional vector view of an array */ template class NXPointRef { public: typedef T value_type; NXPointRef() : m_coords(NULL) {} NXPointRef(T *const v) : m_coords(v) {} ~NXPointRef() {} T const& operator [] (int const& n) const { return m_coords[n]; } T& operator [] (int const& n) { return m_coords[n]; } T *const data(void) { return m_coords; } T const *const data(void) const { return m_coords; } int size(void) const { return N; } NXPointRef& zero(void); NXPointRef& operator += (NXPointRef const& b); NXPointRef& operator -= (NXPointRef const& b); NXPointRef& operator *= (T const& c); NXPointRef& operator /= (T const& c); NXPointRef& normalizeSelf(double const& TOL=NX_DEFAULTTOL); NXPoint normalized(double const& TOL=NX_DEFAULTTOL) const; protected: T *m_coords; static inline T s_sqr(T const& x) { return x*x; } static inline T s_div(T const& a, T const& b) { return (static_cast(a)/static_cast(b)); } }; // typedefs for common instantiations typedef NXPointRef NXPointRef2f; typedef NXPointRef NXPointRef2d; typedef NXPointRef NXPointRef3f; typedef NXPointRef NXPointRef3d; typedef NXPointRef NXPointRef4f; typedef NXPointRef NXPointRef4d; // ------------------------------------------------------------------------ /* CLASS: NXPoint */ /** * N-dimensional point * Allocates private data store and uses NXPointRef to refer to it, inheriting * the latter's functionality */ template class NXPoint : public NXPointRef { public: NXPoint() throw () : NXPointRef(m_coord_data) {} NXPoint(T const& x) throw (NXException); NXPoint(T const& y, T const& y) throw (NXException); NXPoint(T const& x, T const& y, T const& z) throw (NXException); NXPoint(T *const v) throw (); ///< initialize from array NXPoint(NXPointRef const& v) throw (); ///< deep-copy semantics ~NXPoint() {} /// Override inerhited shallow-copy with deep-copy semantics NXPoint& operator = (NXPointRef const& v); private: T m_coord_data[N]; }; // typedefs for common instantiations typedef NXPoint NXPoint2f; typedef NXPoint NXPoint2d; typedef NXPoint NXPoint3f; typedef NXPoint NXPoint3d; typedef NXPoint NXPoint4f; typedef NXPoint NXPoint4d; /* CONSTRUCTOR */ template inline NXPoint::NXPoint(T const& x) throw (NXException) : NXPointRef(m_coord_data) { if(N != 1) throw NXException("Initialization with different dimensionality"); m_coord_data[0] = x; } /* CONSTRUCTOR */ template inline NXPoint::NXPoint(T const& x, T const& y) throw (NXException) : NXPointRef(m_coord_data) { if(N != 2) throw NXException("Initialization with different dimensionality"); m_coord_data[0] = x; m_coord_data[1] = y; } /* CONSTRUCTOR */ template inline NXPoint::NXPoint(T const& x, T const& y, T const& z) throw (NXException) : NXPointRef(m_coord_data) { if(N != 3) throw NXException("Initialization with different dimensionality"); m_coord_data[0] = x; m_coord_data[1] = y; m_coord_data[2] = z; } /* CONSTRUCTOR */ template inline NXPoint::NXPoint(T *const v) throw () : NXPointRef(m_coord_data) { for(int n=0; n NXPoint::NXPoint(NXPointRef const& v) throw () : NXPointRef(m_coord_data) { for(int n=0; n inline NXPoint& NXPoint::operator = (NXPointRef const& v) { for(int n=0; n T dot(NXPointRef& a, NXPointRef& b){ return a[0]*b[0]; } template T dot(NXPointRef& a, NXPointRef& b) { NXPointRef a1(a.data()), b1(b.data()); T const s = dot(a1, b1); T const result = s + a[N-1]*b[N-1]; return result; } template T squared_norm(NXPointRef& v) { return dot(v,v); } template T norm(NXPointRef& v) { return sqrt(squared_norm(v)); } template T length(NXPointRef& v) { return norm(v); } template NXPoint cross(NXPointRef& a, NXPointRef& b) { NXPoint c; c[0] = a[1] * b[2] - a[2] * b[1]; c[1] = a[2] * b[0] - a[0] * b[2]; c[2] = a[0] * b[1] - a[1] * b[0]; return c; } // ------------------------------------------------------------------------ /* NXPointRef member functions */ // template // inline // NXPointRef& NXPointRef::zero(void) // { m_coords[0] = T(0); return *this; } template inline NXPointRef& NXPointRef::zero(void) { for(int n=0; n(m_coords).zero(); m_coords[N-1]=T(0); }*/ return *this; } // increment base-case // template // inline // NXPointRef& NXPointRef::operator += (NXPointRef const& v) // { m_coords[0] += v.m_coords[0]; return *this; } // increment common-case template inline NXPointRef& NXPointRef::operator += (NXPointRef const& v) { for(int n=0; n(m_coords) += NXPointRef(v.m_coords); m_coords[N-1] += v.m_coords[N-1];*/ return *this; } // decrement base-case // template // inline // NXPointRef& NXPointRef::operator -= (NXPointRef const& v) // { m_coords[0] -= v.m_coords[0]; return *this; } // decrement common-case template NXPointRef& NXPointRef::operator -= (NXPointRef const& v) { for(int n=0; n(m_coords) -= NXPointRef(v.m_coords); m_coords[N-1] -= v.m_coords[N-1];*/ return *this; } // scaling base-case // template // inline // NXPointRef& NXPointRef::operator *= (T const& c) // { // m_coords[0] *= c; // return *this; // } // scaling common-case template inline NXPointRef& NXPointRef::operator *= (T const& c) { for(int n=0; n(m_coords) *= c; m_coords[N-1] *= c;*/ return *this; } // scaling base-case // template // inline // NXPointRef& NXPointRef::operator /= (T const& c) // { // m_coords[0] /= c; // return *this; // } // scaling common-case template inline NXPointRef& NXPointRef::operator /= (T const& c) { for(int n=0; n(m_coords) /= c; m_coords[N-1] /= c;*/ return *this; } template inline NXPointRef& NXPointRef::normalizeSelf(double const& TOL) { T const len = norm(*this); if(double(len) < TOL) zero(); else this->operator /= (len); return *this; } template inline NXPoint NXPointRef::normalized(double const& TOL) const { NXPoint v(m_coords); v.normalizeSelf(TOL); return v; } } // Nanorex #endif // NX_POINT_H