/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * This program 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef VECTOR3_H_ #define VECTOR3_H_ /** * Traits class for VECTOR2. */ template <class T> struct VECTOR3_TRAITS { ///< extended range/precision types used by operations involving multiple ///< multiplications to prevent overflow. typedef T extended_type; }; template <> struct VECTOR3_TRAITS<int> { typedef int64_t extended_type; }; /** * Define a general 3D-vector. * * This class uses templates to be universal. Several operators are provided to help * easy implementing of linear algebra equations. * */ template <class T = int> class VECTOR3 { public: typedef typename VECTOR3_TRAITS<T>::extended_type extended_type; typedef T coord_type; static constexpr extended_type ECOORD_MAX = std::numeric_limits<extended_type>::max(); static constexpr extended_type ECOORD_MIN = std::numeric_limits<extended_type>::min(); T x, y, z; /// Construct a 3D-vector with x, y = 0 VECTOR3(); /// Construct a vector with given components x, y VECTOR3( T x, T y, T z ); /// Initializes a vector from another specialization. Beware of rounding /// issues. template <typename CastingType> VECTOR3( const VECTOR3<CastingType>& aVec ) { x = (T) aVec.x; y = (T) aVec.y; z = (T) aVec.z; } /// Copy a vector VECTOR3( const VECTOR3<T>& aVec ) { x = aVec.x; y = aVec.y; z = aVec.z; } /** * Compute cross product of self with \a aVector */ VECTOR3<T> Cross( const VECTOR3<T>& aVector ) const; /** * Compute the dot product of self with \a aVector */ VECTOR3<T>::extended_type Dot( const VECTOR3<T>& aVector ) const; /** * Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2). * * It is used to calculate the length of the vector. * * @return Scalar, the euclidean norm */ T EuclideanNorm() const; /** * Compute the normalized vector. */ VECTOR3<T> Normalize(); ///< Equality operator bool operator==( const VECTOR3<T>& aVector ) const; ///< Not equality operator bool operator!=( const VECTOR3<T>& aVector ) const; }; template <class T> VECTOR3<T>::VECTOR3() { x = y = z = 0.0; } template <class T> VECTOR3<T>::VECTOR3( T aX, T aY, T aZ ) { x = aX; y = aY; z = aZ; } template <class T> VECTOR3<T> VECTOR3<T>::Cross( const VECTOR3<T>& aVector ) const { return VECTOR3<T>( ( y * aVector.z ) - ( z * aVector.y ), ( z * aVector.x ) - ( x * aVector.z ), ( x * aVector.y ) - ( y * aVector.x ) ); } template <class T> typename VECTOR3<T>::extended_type VECTOR3<T>::Dot( const VECTOR3<T>& aVector ) const { return extended_type{x} * extended_type{aVector.x} + extended_type{y} * extended_type{aVector.y} + extended_type{z} * extended_type{aVector.z}; } template <class T> T VECTOR3<T>::EuclideanNorm() const { return sqrt( (extended_type) x * x + (extended_type) y * y + (extended_type) z * z ); } template <class T> VECTOR3<T> VECTOR3<T>::Normalize() { T norm = EuclideanNorm(); x /= norm; y /= norm; z /= norm; return *this; } template <class T> bool VECTOR3<T>::operator==( VECTOR3<T> const& aVector ) const { return ( aVector.x == x ) && ( aVector.y == y ) && ( aVector.z == z ); } template <class T> bool VECTOR3<T>::operator!=( VECTOR3<T> const& aVector ) const { return ( aVector.x != x ) || ( aVector.y != y ) || ( aVector.z != z ); } /* Default specializations */ typedef VECTOR3<double> VECTOR3D; typedef VECTOR3<int> VECTOR3I; typedef VECTOR3<unsigned int> VECTOR3U; #endif // VECTOR3_H_