X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmath%2FSGVec3.hxx;h=56775d3ede34ba6affc15d8fa37076c684311875;hb=66c9187c95fb6861d9737f135fdf68d1bfa265f3;hp=afe7049d80e125038e9096d55b41c62e1ea13058;hpb=9be14a63b1b593b02b5cc3e82edb7a266ae3cbe7;p=simgear.git diff --git a/simgear/math/SGVec3.hxx b/simgear/math/SGVec3.hxx index afe7049d..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 @@ -10,10 +10,9 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // -// You should have received a copy of the GNU Library General Public -// License along with this library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place - Suite 330, -// Boston, MA 02111-1307, USA. +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // #ifndef SGVec3_H @@ -25,6 +24,11 @@ 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) @@ -34,82 +38,78 @@ public: /// uninitialized values in the debug build very fast ... #ifndef NDEBUG for (unsigned i = 0; i < 3; ++i) - _data[i] = SGLimits::quiet_NaN(); + 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; } + { data()[0] = x; data()[1] = y; data()[2] = z; } /// Constructor. Initialize by the content of a plain array, /// make sure it has at least 3 elements - explicit SGVec3(const T* data) - { _data[0] = data[0]; _data[1] = data[1]; _data[2] = data[2]; } - /// Constructor. Initialize by a geodetic coordinate - /// Note that this conversion is relatively expensive to compute - SGVec3(const SGGeod& geod) - { SGGeodesy::SGGeodToCart(geod, *this); } - /// Constructor. Initialize by a geocentric coordinate - /// Note that this conversion is relatively expensive to compute - SGVec3(const SGGeoc& geoc) - { SGGeodesy::SGGeocToCart(geoc, *this); } + explicit SGVec3(const T* d) + { data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; } + 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 - { return _data[i]; } + { return data()[i]; } /// Access by index, the index is unchecked T& operator()(unsigned i) - { return _data[i]; } + { return data()[i]; } /// Access raw data by index, the index is unchecked const T& operator[](unsigned i) const - { return _data[i]; } + { return data()[i]; } /// Access raw data by index, the index is unchecked T& operator[](unsigned i) - { return _data[i]; } + { return data()[i]; } /// Access the x component const T& x(void) const - { return _data[0]; } + { return data()[0]; } /// Access the x component T& x(void) - { return _data[0]; } + { return data()[0]; } /// Access the y component const T& y(void) const - { return _data[1]; } + { return data()[1]; } /// Access the y component T& y(void) - { return _data[1]; } + { return data()[1]; } /// Access the z component const T& z(void) const - { return _data[2]; } + { return data()[2]; } /// Access the z component T& z(void) - { return _data[2]; } + { return data()[2]; } - /// Get the data pointer - const T* data(void) const + /// Readonly raw storage interface + const T (&data(void) const)[3] { return _data; } - /// Get the data pointer - T* data(void) - { return _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] + /// Readonly raw storage interface + T (&data(void))[3] { return _data; } /// Inplace addition SGVec3& operator+=(const SGVec3& v) - { _data[0] += v(0); _data[1] += v(1); _data[2] += v(2); return *this; } + { data()[0] += v(0); data()[1] += v(1); data()[2] += v(2); return *this; } /// Inplace subtraction SGVec3& operator-=(const SGVec3& v) - { _data[0] -= v(0); _data[1] -= v(1); _data[2] -= v(2); return *this; } + { data()[0] -= v(0); data()[1] -= v(1); data()[2] -= v(2); return *this; } /// Inplace scalar multiplication template SGVec3& operator*=(S s) - { _data[0] *= s; _data[1] *= s; _data[2] *= s; return *this; } + { data()[0] *= s; data()[1] *= s; data()[2] *= s; return *this; } /// Inplace scalar multiplication by 1/s template SGVec3& operator/=(S s) @@ -126,11 +126,57 @@ public: static SGVec3 e3(void) { return SGVec3(0, 0, 1); } + /// Constructor. Initialize by a geodetic coordinate + /// Note that this conversion is relatively expensive to compute + static SGVec3 fromGeod(const SGGeod& geod); + /// Constructor. Initialize by a geocentric coordinate + /// Note that this conversion is relatively expensive to compute + static SGVec3 fromGeoc(const SGGeoc& geoc); + private: - /// The actual data T _data[3]; }; +template<> +inline +SGVec3 +SGVec3::fromGeod(const SGGeod& geod) +{ + SGVec3 cart; + SGGeodesy::SGGeodToCart(geod, cart); + return cart; +} + +template<> +inline +SGVec3 +SGVec3::fromGeod(const SGGeod& geod) +{ + SGVec3 cart; + SGGeodesy::SGGeodToCart(geod, cart); + return SGVec3(cart(0), cart(1), cart(2)); +} + +template<> +inline +SGVec3 +SGVec3::fromGeoc(const SGGeoc& geoc) +{ + SGVec3 cart; + SGGeodesy::SGGeocToCart(geoc, cart); + return cart; +} + +template<> +inline +SGVec3 +SGVec3::fromGeoc(const SGGeoc& geoc) +{ + SGVec3 cart; + SGGeodesy::SGGeocToCart(geoc, cart); + return SGVec3(cart(0), cart(1), cart(2)); +} + /// Unary +, do nothing ... template inline @@ -173,6 +219,73 @@ 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 +SGVec3 +min(const SGVec3& v1, const SGVec3& v2) +{ + return SGVec3(SGMisc::min(v1(0), v2(0)), + SGMisc::min(v1(1), v2(1)), + SGMisc::min(v1(2), v2(2))); +} +template +inline +SGVec3 +min(const SGVec3& v, S s) +{ + return SGVec3(SGMisc::min(s, v(0)), + SGMisc::min(s, v(1)), + SGMisc::min(s, v(2))); +} +template +inline +SGVec3 +min(S s, const SGVec3& v) +{ + return SGVec3(SGMisc::min(s, v(0)), + SGMisc::min(s, v(1)), + SGMisc::min(s, v(2))); +} + +/// component wise max +template +inline +SGVec3 +max(const SGVec3& v1, const SGVec3& v2) +{ + return SGVec3(SGMisc::max(v1(0), v2(0)), + SGMisc::max(v1(1), v2(1)), + SGMisc::max(v1(2), v2(2))); +} +template +inline +SGVec3 +max(const SGVec3& v, S s) +{ + return SGVec3(SGMisc::max(s, v(0)), + SGMisc::max(s, v(1)), + SGMisc::max(s, v(2))); +} +template +inline +SGVec3 +max(S s, const SGVec3& v) +{ + return SGVec3(SGMisc::max(s, v(0)), + SGMisc::max(s, v(1)), + SGMisc::max(s, v(2))); +} + /// Scalar dot product template inline @@ -202,6 +315,13 @@ T norm1(const SGVec3& v) { return fabs(v(0)) + fabs(v(1)) + fabs(v(2)); } +/// The inf-norm of the vector +template +inline +T +normI(const SGVec3& v) +{ return SGMisc::max(fabs(v(0)), fabs(v(1)), fabs(v(2))); } + /// Vector cross product template inline @@ -213,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 @@ -234,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 @@ -258,6 +446,32 @@ equivalent(const SGVec3& v1, const SGVec3& v2) return equivalent(v1, v2, tol, tol); } +/// The euclidean distance of the two vectors +template +inline +T +dist(const SGVec3& v1, const SGVec3& v2) +{ return norm(v1 - v2); } + +/// The squared euclidean distance of the two vectors +template +inline +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 @@ -276,10 +490,6 @@ std::basic_ostream& operator<<(std::basic_ostream& s, const SGVec3& v) { return s << "[ " << v(0) << ", " << v(1) << ", " << v(2) << " ]"; } -/// Two classes doing actually the same on different types -typedef SGVec3 SGVec3f; -typedef SGVec3 SGVec3d; - inline SGVec3f toVec3f(const SGVec3d& v)