/******************************************************************************* * CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * * version 0.1 * * Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg * * * * This library is free software; you can redistribute it and/or modify it * * under the terms of the GNU Lesser General Public License as published by the * * Free Software Foundation; either version 2.1 of the License, or (at your * * option) any later version. * * * * This library is distributed in the hope that it will be useful, but WITHOUT * * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * * for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this library; if not, write to the Free Software Foundation, * * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * * * Web site: http://cgogn.unistra.fr/ * * Contact information: cgogn@unistra.fr * * * *******************************************************************************/ #include #include namespace CGoGN { namespace Geom { template std::string Vector::CGoGNnameOfType() { std::stringstream ss ; ss << "Geom::Vector<" ; ss << DIM ; ss << "," ; ss << nameOfType(T()) ; ss << ">" ; return ss.str() ; } /**********************************************/ /* CONSTRUCTORS */ /**********************************************/ template Vector::Vector() { CGoGN_STATIC_ASSERT(DIM > 0, invalid_zero_dimensional_Vector) ; zero() ; } template Vector::Vector(const Vector& v) { for (unsigned int i = 0; i < DIM; ++i) m_data[i] = v[i] ; } template template Vector::Vector(const Vector& v) { for (unsigned int i = 0; i < DIM; ++i) m_data[i] = T(v[i]) ; } template Vector::Vector(T x, T y) { CGoGN_STATIC_ASSERT(DIM == 2, incompatible_Vector_constructor_dimension) ; m_data[0] = x ; m_data[1] = y ; } template Vector::Vector(T x, T y, T z) { CGoGN_STATIC_ASSERT(DIM == 3, incompatible_Vector_constructor_dimension) ; m_data[0] = x ; m_data[1] = y ; m_data[2] = z ; } template Vector::Vector(T x, T y, T z, T w) { CGoGN_STATIC_ASSERT(DIM == 4, incompatible_Vector_constructor_dimension) ; m_data[0] = x ; m_data[1] = y ; m_data[2] = z ; m_data[3] = w ; } template Vector::Vector(T x) { set(x) ; } template inline void Vector::set(T a) { for (unsigned int i = 0; i < DIM; ++i) m_data[i] = a ; } template inline void Vector::zero() { set(T(0)) ; } /**********************************************/ /* ACCESSORS */ /**********************************************/ template inline T& Vector::operator[](unsigned int index) { assert(index < DIM) ; return m_data[index] ; } template inline const T& Vector::operator[](unsigned int index) const { assert(index < DIM) ; return m_data[index] ; } template inline unsigned int Vector::dimension() const { return DIM ; } template inline T* Vector::data() { return m_data ; } template inline const T* Vector::data() const { return m_data ; } /**********************************************/ /* ARITHMETIC SELF-OPERATORS */ /**********************************************/ template inline Vector& Vector::operator+=(const Vector& v) { for (unsigned int i = 0; i < DIM; ++i) m_data[i] += v[i] ; return *this ; } template inline Vector& Vector::operator-=(const Vector& v) { for (unsigned int i = 0; i < DIM; ++i) m_data[i] -= v[i] ; return *this ; } template inline Vector& Vector::operator*=(T a) { for (unsigned int i = 0; i < DIM; ++i) m_data[i] *= a ; return *this ; } template inline Vector& Vector::operator/=(T a) { for (unsigned int i = 0; i < DIM; ++i) m_data[i] /= a ; return *this ; } /**********************************************/ /* ARITHMETIC OPERATORS */ /**********************************************/ template inline Vector Vector::operator+(const Vector& v) const { Vector res ; for (unsigned int i = 0; i < DIM; ++i) res[i] = m_data[i] + v[i] ; return res ; } template inline Vector Vector::operator-(const Vector& v) const { Vector res ; for (unsigned int i = 0; i < DIM; ++i) res[i] = m_data[i] - v[i] ; return res ; } template inline Vector Vector::operator-() const { Vector res ; for (unsigned int i = 0; i < DIM; ++i) res[i] = - m_data[i] ; return res ; } template inline Vector Vector::operator*(T a) const { Vector res ; for (unsigned int i = 0; i < DIM; ++i) res[i] = m_data[i] * a ; return res ; } template inline Vector Vector::operator/(T a) const { Vector res ; for (unsigned int i = 0; i < DIM; ++i) res[i] = m_data[i] / a ; return res ; } /**********************************************/ /* UTILITY FUNCTIONS */ /**********************************************/ template inline T Vector::norm2() const { T n(0) ; for (unsigned int i = 0; i < DIM; ++i) n += m_data[i] * m_data[i] ; return n ; } template inline double Vector::norm() const { return sqrt(norm2()) ; } template inline double Vector::normalize() { double n = norm() ; if (n != T(0)) for (unsigned int i = 0; i < DIM; ++i) m_data[i] /= T(n) ; return n ; } template inline Vector Vector::normalized() const { Vector v(*this); v.normalize(); return v; } template inline T Vector::operator*(const Vector v) const { T d(0) ; for (unsigned int i = 0; i < DIM; ++i) d += m_data[i] * v[i] ; return d ; } template inline Vector Vector::operator^(const Vector v) const { CGoGN_STATIC_ASSERT(DIM == 3, incompatible_Vector_cross_product_dimension) ; Vector c ; c[0] = m_data[1] * v[2] - m_data[2] * v[1] ; c[1] = m_data[2] * v[0] - m_data[0] * v[2] ; c[2] = m_data[0] * v[1] - m_data[1] * v[0] ; return c ; } template inline bool Vector::operator==(const Vector& v) const { for (unsigned int i = 0; i < DIM; ++i) if (v[i] != m_data[i]) return false ; return true ; } template inline bool Vector::operator!=(const Vector& v) const { for (unsigned int i = 0; i < DIM; ++i) if (v[i] != m_data[i]) return true ; return false ; } template inline bool Vector::hasNan() const { for (unsigned int i = 0; i < DIM; ++i) if (m_data[i] != m_data[i]) return true ; return false ; } template inline bool Vector::isFinite() const { for (unsigned int i = 0; i < DIM; ++i) if (!std::isfinite(m_data[i])) return false ; return true ; } template inline bool Vector::isNormalized(const T& epsilon) const { return (1 - epsilon < norm2() && norm2() < 1 + epsilon) ; } template inline bool Vector::isOrthogonal(const Vector& v, const T& epsilon) const { return (fabs(v * (*this)) < epsilon) ; } template inline bool Vector::isNear(const Vector& v, int precision) const { T diff ; T norm2(0) ; for (unsigned int i = 0 ; i < DIM ; ++i) { diff = m_data[i] - v[i] ; if (!isNull(diff, precision)) return false ; norm2 += diff * diff ; } return isNull2(norm2, precision) ; } /**********************************************/ /* STREAM OPERATORS */ /**********************************************/ template std::ostream& operator<<(std::ostream& out, const Vector& v) { for (unsigned int i = 0; i < DIM; ++i) out << v[i] << " " ; return out ; } template std::istream& operator>>(std::istream& in, Vector& v) { for (unsigned int i = 0; i < DIM; ++i) in >> v[i] ; return in ; } /*** * Test if x is null within precision. * 3 cases are possible : * - precision = 0 : x is null <=> (x == 0) * - precision > 0 : x is null <=> (|x| < precision) * - precision < 0 : x is null <=> (|x| < 1/precision) <=> (precision * |x| < 1) */ template inline bool isNull(T x, int precision) { if (precision == 0) return (x == 0) ; else if (precision > 0) return (fabs(x) < precision) ; else return (precision * fabs(x) < 1) ; } /*** * Test if the square root of x is null within precision. * In other words, test if x is null within precision*precision */ template inline bool isNull2(T x, int precision) { if (precision == 0) return (x == 0) ; else if (precision > 0) return (isNull(x, precision * precision)) ; else return (isNull(x, - (precision * precision))) ; } template inline Vector operator*(T2 b, const Vector& v) { return v * T(b) ; } template inline Vector operator/(T a, const Vector& v) { return v / a ; } template inline T tripleProduct(const Vector& v1, const Vector& v2, const Vector& v3) { return v1 * (v2 ^ v3) ; } template inline Vector slerp(const Vector& v1, const Vector& v2, const T& t) { Vector res ; T scal = v1 * v2 ; // Prevention for floating point errors if (1 < scal && scal < 1 + 1e-6) scal = T(1) ; if (-1. - 1e-6 < scal && scal < -1) scal = -T(1) ; T omega = acos(scal) ; T den = sin(omega) ; if (-1e-8 < den && den < 1e-8) return t < 0.5 ? v1 : v2 ; T f1 = sin((T(1) - t) * omega) / den ; // assume 0 <= t <= 1 T f2 = sin(t * omega) / den ; res += f1 * v1 ; res += f2 * v2 ; return res ; } } // namespace Geom } // namespace CGoGN