diff options
Diffstat (limited to 'include/math/vector2d.h')
-rw-r--r-- | include/math/vector2d.h | 579 |
1 files changed, 579 insertions, 0 deletions
diff --git a/include/math/vector2d.h b/include/math/vector2d.h new file mode 100644 index 0000000..bba2a4a --- /dev/null +++ b/include/math/vector2d.h @@ -0,0 +1,579 @@ +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 2010 Virtenio GmbH, Torsten Hueter, torsten.hueter <at> virtenio.de + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors. + * Copyright (C) 2013 CERN + * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> + * + * 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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef VECTOR2D_H_ +#define VECTOR2D_H_ + +#include <cmath> +#include <climits> +#include <iostream> +#include <sstream> +#include <cmath> + +#include <math/math_util.h> + +#ifdef WX_COMPATIBILITY + #include <wx/gdicmn.h> +#endif + +/** + * Class VECTOR2_TRAITS + * traits class for VECTOR2. + */ +template <class T> +struct VECTOR2_TRAITS +{ + ///> extended range/precision types used by operations involving multiple + ///> multiplications to prevent overflow. + typedef T extended_type; +}; + +template <> +struct VECTOR2_TRAITS<int> +{ + typedef int64_t extended_type; + static const extended_type ECOORD_MAX = 0x7fffffffffffffffULL; + static const extended_type ECOORD_MIN = 0x8000000000000000ULL; +}; + +// Forward declarations for template friends +template <class T> +class VECTOR2; +template <class T> +std::ostream& operator<<( std::ostream& aStream, const VECTOR2<T>& aVector ); + +/** + * Class VECTOR2 + * defines a general 2D-vector/point. + * + * This class uses templates to be universal. Several operators are provided to help + * easy implementing of linear algebra equations. + * + */ +template <class T = int> +class VECTOR2 : public VECTOR2_TRAITS<T> +{ +public: + typedef typename VECTOR2_TRAITS<T>::extended_type extended_type; + typedef T coord_type; + + T x, y; + + // Constructors + + /// Construct a 2D-vector with x, y = 0 + VECTOR2(); + +#ifdef WX_COMPATIBILITY + /// Constructor with a wxPoint as argument + VECTOR2( const wxPoint& aPoint ); + + /// Constructor with a wxSize as argument + VECTOR2( const wxSize& aSize ); +#endif + + /// Construct a vector with given components x, y + VECTOR2( T x, T y ); + + /// Initializes a vector from another specialization. Beware of rouding + /// issues. + template <typename CastingType> + VECTOR2( const VECTOR2<CastingType>& aVec ) + { + x = (T) aVec.x; + y = (T) aVec.y; + } + + /// Casts a vector to another specialized subclass. Beware of rouding + /// issues. + template <typename CastedType> + VECTOR2<CastedType> operator()() const + { + return VECTOR2<CastedType>( (CastedType) x, (CastedType) y ); + } + + /// Destructor + // virtual ~VECTOR2(); + + /** + * Function Euclidean Norm + * computes 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; + + /** + * Function Squared Euclidean Norm + * computes the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2). + * It is used to calculate the length of the vector. + * @return Scalar, the euclidean norm + */ + extended_type SquaredEuclideanNorm() const; + + + /** + * Function Perpendicular + * computes the perpendicular vector + * @return Perpendicular vector + */ + VECTOR2<T> Perpendicular() const; + + /** + * Function Resize + * returns a vector of the same direction, but length specified in aNewLength + * @param aNewLength: length of the rescaled vector + * @return rescaled vector + */ + VECTOR2<T> Resize( T aNewLength ) const; + + /** + * Function Angle + * computes the angle of the vector + * @return vector angle, in radians + */ + double Angle() const; + + /** + * Function Rotate + * rotates the vector by a given angle + * @param aAngle rotation angle in radians + * @return rotated vector + */ + VECTOR2<T> Rotate( double aAngle ) const; + + /** + * Function Format + * returns the vector formatted as a string + * @return the formatted string + */ + const std::string Format() const; + + /** + * Function Cross() + * computes cross product of self with aVector + */ + extended_type Cross( const VECTOR2<T>& aVector ) const; + + /** + * Function Dot() + * computes dot product of self with aVector + */ + extended_type Dot( const VECTOR2<T>& aVector ) const; + + + // Operators + + /// Assignment operator + VECTOR2<T>& operator=( const VECTOR2<T>& aVector ); + + /// Vector addition operator + VECTOR2<T> operator+( const VECTOR2<T>& aVector ) const; + + /// Scalar addition operator + VECTOR2<T> operator+( const T& aScalar ) const; + + /// Compound assignment operator + VECTOR2<T>& operator+=( const VECTOR2<T>& aVector ); + + /// Compound assignment operator + VECTOR2<T>& operator+=( const T& aScalar ); + + /// Vector subtraction operator + VECTOR2<T> operator-( const VECTOR2<T>& aVector ) const; + + /// Scalar subtraction operator + VECTOR2<T> operator-( const T& aScalar ) const; + + /// Compound assignment operator + VECTOR2<T>& operator-=( const VECTOR2<T>& aVector ); + + /// Compound assignment operator + VECTOR2<T>& operator-=( const T& aScalar ); + + /// Negate Vector operator + VECTOR2<T> operator-(); + + /// Scalar product operator + extended_type operator*( const VECTOR2<T>& aVector ) const; + + /// Multiplication with a factor + VECTOR2<T> operator*( const T& aFactor ) const; + + /// Division with a factor + VECTOR2<T> operator/( const T& aFactor ) const; + + /// Equality operator + bool operator==( const VECTOR2<T>& aVector ) const; + + /// Not equality operator + bool operator!=( const VECTOR2<T>& aVector ) const; + + /// Smaller than operator + bool operator<( const VECTOR2<T>& aVector ) const; + bool operator<=( const VECTOR2<T>& aVector ) const; + + /// Greater than operator + bool operator>( const VECTOR2<T>& aVector ) const; + bool operator>=( const VECTOR2<T>& aVector ) const; + + friend std::ostream & operator<< <T> ( std::ostream & stream, const VECTOR2<T> &vector ); +}; + + +// ---------------------- +// --- Implementation --- +// ---------------------- + +template <class T> +VECTOR2<T>::VECTOR2() +{ + x = y = 0.0; +} + + +#ifdef WX_COMPATIBILITY +template <class T> +VECTOR2<T>::VECTOR2( wxPoint const& aPoint ) +{ + x = T( aPoint.x ); + y = T( aPoint.y ); +} + + +template <class T> +VECTOR2<T>::VECTOR2( wxSize const& aSize ) +{ + x = T( aSize.x ); + y = T( aSize.y ); +} +#endif + +template <class T> +VECTOR2<T>::VECTOR2( T aX, T aY ) +{ + x = aX; + y = aY; +} + + +template <class T> +T VECTOR2<T>::EuclideanNorm() const +{ + return sqrt( (extended_type) x * x + (extended_type) y * y ); +} + + +template <class T> +typename VECTOR2<T>::extended_type VECTOR2<T>::SquaredEuclideanNorm() const +{ + return (extended_type) x * x + (extended_type) y * y; +} + + +template <class T> +double VECTOR2<T>::Angle() const +{ + return atan2( y, x ); +} + + +template <class T> +VECTOR2<T> VECTOR2<T>::Perpendicular() const +{ + VECTOR2<T> perpendicular( -y, x ); + return perpendicular; +} + + +template <class T> +VECTOR2<T>& VECTOR2<T>::operator=( const VECTOR2<T>& aVector ) +{ + x = aVector.x; + y = aVector.y; + return *this; +} + + +template <class T> +VECTOR2<T>& VECTOR2<T>::operator+=( const VECTOR2<T>& aVector ) +{ + x += aVector.x; + y += aVector.y; + return *this; +} + + +template <class T> +VECTOR2<T>& VECTOR2<T>::operator+=( const T& aScalar ) +{ + x += aScalar; + y += aScalar; + return *this; +} + + +template <class T> +VECTOR2<T>& VECTOR2<T>::operator-=( const VECTOR2<T>& aVector ) +{ + x -= aVector.x; + y -= aVector.y; + return *this; +} + + +template <class T> +VECTOR2<T>& VECTOR2<T>::operator-=( const T& aScalar ) +{ + x -= aScalar; + y -= aScalar; + return *this; +} + + +template <class T> +VECTOR2<T> VECTOR2<T>::Rotate( double aAngle ) const +{ + double sa = sin( aAngle ); + double ca = cos( aAngle ); + + return VECTOR2<T> ( T( (double) x * ca - (double) y * sa ), + T( (double) x * sa + (double) y * ca ) ); +} + + +template <class T> +VECTOR2<T> VECTOR2<T>::Resize( T aNewLength ) const +{ + if( x == 0 && y == 0 ) + return VECTOR2<T> ( 0, 0 ); + + extended_type l_sq_current = (extended_type) x * x + (extended_type) y * y; + extended_type l_sq_new = (extended_type) aNewLength * aNewLength; + + return VECTOR2<T> ( + ( x < 0 ? -1 : 1 ) * sqrt( rescale( l_sq_new, (extended_type) x * x, l_sq_current ) ), + ( y < 0 ? -1 : 1 ) * sqrt( rescale( l_sq_new, (extended_type) y * y, l_sq_current ) ) ) * sign( aNewLength ); +} + + +template <class T> +const std::string VECTOR2<T>::Format() const +{ + std::stringstream ss; + + ss << "( xy " << x << " " << y << " )"; + + return ss.str(); +} + + +template <class T> +VECTOR2<T> VECTOR2<T>::operator+( const VECTOR2<T>& aVector ) const +{ + return VECTOR2<T> ( x + aVector.x, y + aVector.y ); +} + + +template <class T> +VECTOR2<T> VECTOR2<T>::operator+( const T& aScalar ) const +{ + return VECTOR2<T> ( x + aScalar, y + aScalar ); +} + + +template <class T> +VECTOR2<T> VECTOR2<T>::operator-( const VECTOR2<T>& aVector ) const +{ + return VECTOR2<T> ( x - aVector.x, y - aVector.y ); +} + + +template <class T> +VECTOR2<T> VECTOR2<T>::operator-( const T& aScalar ) const +{ + return VECTOR2<T> ( x - aScalar, y - aScalar ); +} + + +template <class T> +VECTOR2<T> VECTOR2<T>::operator-() +{ + return VECTOR2<T> ( -x, -y ); +} + + +template <class T> +typename VECTOR2<T>::extended_type VECTOR2<T>::operator*( const VECTOR2<T>& aVector ) const +{ + return aVector.x * x + aVector.y * y; +} + + +template <class T> +VECTOR2<T> VECTOR2<T>::operator*( const T& aFactor ) const +{ + VECTOR2<T> vector( x * aFactor, y * aFactor ); + return vector; +} + + +template <class T> +VECTOR2<T> VECTOR2<T>::operator/( const T& aFactor ) const +{ + VECTOR2<T> vector( x / aFactor, y / aFactor ); + return vector; +} + + +template <class T> +VECTOR2<T> operator*( const T& aFactor, const VECTOR2<T>& aVector ) +{ + VECTOR2<T> vector( aVector.x * aFactor, aVector.y * aFactor ); + return vector; +} + + +template <class T> +typename VECTOR2<T>::extended_type VECTOR2<T>::Cross( const VECTOR2<T>& aVector ) const +{ + return (extended_type) x * (extended_type) aVector.y - + (extended_type) y * (extended_type) aVector.x; +} + + +template <class T> +typename VECTOR2<T>::extended_type VECTOR2<T>::Dot( const VECTOR2<T>& aVector ) const +{ + return (extended_type) x * (extended_type) aVector.x + + (extended_type) y * (extended_type) aVector.y; +} + + +template <class T> +bool VECTOR2<T>::operator<( const VECTOR2<T>& aVector ) const +{ + return ( *this * *this ) < ( aVector * aVector ); +} + + +template <class T> +bool VECTOR2<T>::operator<=( const VECTOR2<T>& aVector ) const +{ + return ( *this * *this ) <= ( aVector * aVector ); +} + + +template <class T> +bool VECTOR2<T>::operator>( const VECTOR2<T>& aVector ) const +{ + return ( *this * *this ) > ( aVector * aVector ); +} + + +template <class T> +bool VECTOR2<T>::operator>=( const VECTOR2<T>& aVector ) const +{ + return ( *this * *this ) >= ( aVector * aVector ); +} + + +template <class T> +bool VECTOR2<T>::operator==( VECTOR2<T> const& aVector ) const +{ + return ( aVector.x == x ) && ( aVector.y == y ); +} + + +template <class T> +bool VECTOR2<T>::operator!=( VECTOR2<T> const& aVector ) const +{ + return ( aVector.x != x ) || ( aVector.y != y ); +} + + +template <class T> +const VECTOR2<T> LexicographicalMax( const VECTOR2<T>& aA, const VECTOR2<T>& aB ) +{ + if( aA.x > aB.x ) + return aA; + else if( aA.x == aB.x && aA.y > aB.y ) + return aA; + + return aB; +} + + +template <class T> +const VECTOR2<T> LexicographicalMin( const VECTOR2<T>& aA, const VECTOR2<T>& aB ) +{ + if( aA.x < aB.x ) + return aA; + else if( aA.x == aB.x && aA.y < aB.y ) + return aA; + + return aB; +} + + +template <class T> +const int LexicographicalCompare( const VECTOR2<T>& aA, const VECTOR2<T>& aB ) +{ + if( aA.x < aB.x ) + return -1; + else if( aA.x > aB.x ) + return 1; + else // aA.x == aB.x + { + if( aA.y < aB.y ) + return -1; + else if( aA.y > aB.y ) + return 1; + else + return 0; + } +} + + +template <class T> +std::ostream& operator<<( std::ostream& aStream, const VECTOR2<T>& aVector ) +{ + aStream << "[ " << aVector.x << " | " << aVector.y << " ]"; + return aStream; +} + + +/* Default specializations */ +typedef VECTOR2<double> VECTOR2D; +typedef VECTOR2<int> VECTOR2I; + +/* Compatibility typedefs */ +// FIXME should be removed to avoid multiple typedefs for the same type +typedef VECTOR2<double> DPOINT; +typedef DPOINT DSIZE; + +#endif // VECTOR2D_H_ |