X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmath%2FSGVec3.hxx;h=56775d3ede34ba6affc15d8fa37076c684311875;hb=66c9187c95fb6861d9737f135fdf68d1bfa265f3;hp=4d3100b5945fac7fc54c8daada44f78e9f7e6152;hpb=bd3518637cb9477313427745eff4038e0dafedfe;p=simgear.git diff --git a/simgear/math/SGVec3.hxx b/simgear/math/SGVec3.hxx index 4d3100b5..56775d3e 100644 --- a/simgear/math/SGVec3.hxx +++ b/simgear/math/SGVec3.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2006 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2006-2009 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -18,61 +18,17 @@ #ifndef SGVec3_H #define SGVec3_H -#include -#include - -template -struct SGVec3Storage { - /// Readonly raw storage interface - const T (&data(void) const)[3] - { return _data; } - /// Readonly raw storage interface - T (&data(void))[3] - { return _data; } - - void osg() const - { } - -private: - T _data[3]; -}; - -template<> -struct SGVec3Storage : public osg::Vec3f { - /// Access raw data by index, the index is unchecked - const float (&data(void) const)[3] - { return osg::Vec3f::_v; } - /// Access raw data by index, the index is unchecked - float (&data(void))[3] - { return osg::Vec3f::_v; } - - const osg::Vec3f& osg() const - { return *this; } - osg::Vec3f& osg() - { return *this; } -}; - -template<> -struct SGVec3Storage : public osg::Vec3d { - /// Access raw data by index, the index is unchecked - const double (&data(void) const)[3] - { return osg::Vec3d::_v; } - /// Access raw data by index, the index is unchecked - double (&data(void))[3] - { return osg::Vec3d::_v; } - - const osg::Vec3d& osg() const - { return *this; } - osg::Vec3d& osg() - { return *this; } -}; - /// 3D Vector Class template -class SGVec3 : protected SGVec3Storage { +class SGVec3 { public: typedef T value_type; +#ifdef __GNUC__ +// Avoid "_data not initialized" warnings (see comment below). +# pragma GCC diagnostic ignored "-Wuninitialized" +#endif + /// Default constructor. Does not initialize at all. /// If you need them zero initialized, use SGVec3::zeros() SGVec3(void) @@ -85,6 +41,12 @@ public: data()[i] = SGLimits::quiet_NaN(); #endif } + +#ifdef __GNUC__ + // Restore warning settings. +# pragma GCC diagnostic warning "-Wuninitialized" +#endif + /// Constructor. Initialize by the given values SGVec3(T x, T y, T z) { data()[0] = x; data()[1] = y; data()[2] = z; } @@ -92,10 +54,11 @@ public: /// make sure it has at least 3 elements explicit SGVec3(const T* d) { data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; } - explicit SGVec3(const osg::Vec3f& d) - { data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; } - explicit SGVec3(const osg::Vec3d& d) + template + explicit SGVec3(const SGVec3& d) { data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; } + explicit SGVec3(const SGVec2& v2, const T& v3 = 0) + { data()[0] = v2[0]; data()[1] = v2[1]; data()[2] = v3; } /// Access by index, the index is unchecked const T& operator()(unsigned i) const @@ -130,18 +93,12 @@ public: T& z(void) { return data()[2]; } - /// Get the data pointer - using SGVec3Storage::data; - - /// Readonly interface function to ssg's sgVec3/sgdVec3 - const T (&sg(void) const)[3] - { return data(); } - /// Interface function to ssg's sgVec3/sgdVec3 - T (&sg(void))[3] - { return data(); } - - /// Interface function to osg's Vec3* - using SGVec3Storage::osg; + /// Readonly raw storage interface + const T (&data(void) const)[3] + { return _data; } + /// Readonly raw storage interface + T (&data(void))[3] + { return _data; } /// Inplace addition SGVec3& operator+=(const SGVec3& v) @@ -175,6 +132,9 @@ public: /// Constructor. Initialize by a geocentric coordinate /// Note that this conversion is relatively expensive to compute static SGVec3 fromGeoc(const SGGeoc& geoc); + +private: + T _data[3]; }; template<> @@ -259,6 +219,15 @@ SGVec3 operator*(const SGVec3& v, S s) { return SGVec3(s*v(0), s*v(1), s*v(2)); } +/// multiplication as a multiplicator, that is assume that the first vector +/// represents a 3x3 diagonal matrix with the diagonal elements in the vector. +/// Then the result is the product of that matrix times the second vector. +template +inline +SGVec3 +mult(const SGVec3& v1, const SGVec3& v2) +{ return SGVec3(v1(0)*v2(0), v1(1)*v2(1), v1(2)*v2(2)); } + /// component wise min template inline @@ -364,12 +333,43 @@ cross(const SGVec3& v1, const SGVec3& v2) v1(0)*v2(1) - v1(1)*v2(0)); } -/// The euclidean norm of the vector, that is what most people call length +/// return any normalized vector perpendicular to v +template +inline +SGVec3 +perpendicular(const SGVec3& v) +{ + T absv1 = fabs(v(0)); + T absv2 = fabs(v(1)); + T absv3 = fabs(v(2)); + + if (absv2 < absv1 && absv3 < absv1) { + T quot = v(1)/v(0); + return (1/sqrt(1+quot*quot))*SGVec3(quot, -1, 0); + } else if (absv3 < absv2) { + T quot = v(2)/v(1); + return (1/sqrt(1+quot*quot))*SGVec3(0, quot, -1); + } else if (SGLimits::min() < absv3) { + T quot = v(0)/v(2); + return (1/sqrt(1+quot*quot))*SGVec3(-1, 0, quot); + } else { + // the all zero case ... + return SGVec3(0, 0, 0); + } +} + +/// Construct a unit vector in the given direction. +/// or the zero vector if the input vector is zero. template inline SGVec3 normalize(const SGVec3& v) -{ return (1/norm(v))*v; } +{ + T normv = norm(v); + if (normv <= SGLimits::min()) + return SGVec3::zeros(); + return (1/normv)*v; +} /// Return true if exactly the same template @@ -385,6 +385,43 @@ bool operator!=(const SGVec3& v1, const SGVec3& v2) { return ! (v1 == v2); } +/// Return true if smaller, good for putting that into a std::map +template +inline +bool +operator<(const SGVec3& v1, const SGVec3& v2) +{ + if (v1(0) < v2(0)) return true; + else if (v2(0) < v1(0)) return false; + else if (v1(1) < v2(1)) return true; + else if (v2(1) < v1(1)) return false; + else return (v1(2) < v2(2)); +} + +template +inline +bool +operator<=(const SGVec3& v1, const SGVec3& v2) +{ + if (v1(0) < v2(0)) return true; + else if (v2(0) < v1(0)) return false; + else if (v1(1) < v2(1)) return true; + else if (v2(1) < v1(1)) return false; + else return (v1(2) <= v2(2)); +} + +template +inline +bool +operator>(const SGVec3& v1, const SGVec3& v2) +{ return operator<(v2, v1); } + +template +inline +bool +operator>=(const SGVec3& v1, const SGVec3& v2) +{ return operator<=(v2, v1); } + /// Return true if equal to the relative tolerance tol template inline @@ -423,6 +460,18 @@ T distSqr(const SGVec3& v1, const SGVec3& v2) { SGVec3 tmp = v1 - v2; return dot(tmp, tmp); } +// calculate the projection of u along the direction of d. +template +inline +SGVec3 +projection(const SGVec3& u, const SGVec3& d) +{ + T denom = dot(d, d); + T ud = dot(u, d); + if (SGLimits::min() < denom) return u; + else return d * (dot(u, d) / denom); +} + #ifndef NDEBUG template inline