kicad/include/vector2d.h

415 lines
11 KiB
C++

/*
* 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.
*
* 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 <wx/gdicmn.h> // For wxPoint definition
/// Forward declaration for template friends
//template<class T> class VECTOR2;
/**
* Class VECTOR2
* defines a general 2D-vector.
*
* This class uses templates to be universal. Several operators are provided to help easy implementing
* of linear algebra equations.
*
*/
template<class T> class VECTOR2
{
public:
T x, y;
// Constructors
/// Construct a 2D-vector with x, y = 0
VECTOR2();
/// Constructor with a wxPoint as argument
VECTOR2( const wxPoint& aPoint );
/// Constructor with a wxSize as argument
VECTOR2( const wxSize& aSize );
/// Construct a vector with given components x, y
VECTOR2( T x, T 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();
/**
* Function Perpendicular
* computes the perpendicular vector
* @return Perpendicular vector
*/
VECTOR2<T> Perpendicular();
/**
* Function Angle
* computes the angle of the vector
* @return vector angle
*/
T Angle();
// Operators
/// Assignment operator
VECTOR2<T>& operator=( const VECTOR2<T>& aVector );
/// Vector addition operator
VECTOR2<T> operator+( const VECTOR2<T>& aVector );
/// Compound assignment operator
VECTOR2<T>& operator+=( const VECTOR2<T>& aVector );
/// Vector subtraction operator
VECTOR2<T> operator-( const VECTOR2<T>& aVector );
/// Compound assignment operator
VECTOR2<T>& operator-=( const VECTOR2<T>& aVector );
/// Negate Vector operator
VECTOR2<T> operator-();
/// Scalar product operator
T operator*( const VECTOR2<T>& aVector );
/// Multiplication with a factor
VECTOR2<T> operator*( const T& aFactor );
/// Cross product operator
T operator^( const VECTOR2<T>& aVector );
/// Equality operator
const bool operator==( const VECTOR2<T>& aVector );
/// Not equality operator
const bool operator!=( const VECTOR2<T>& aVector );
/// Smaller than operator
bool operator<( const VECTOR2<T>& aVector );
bool operator<=( const VECTOR2<T>& aVector );
/// Greater than operator
bool operator>( const VECTOR2<T>& aVector );
bool operator>=( const VECTOR2<T>& aVector );
/// Casting to int vector
// operator VECTOR2<int>();
/// Type casting operator for the class wxPoint
//operator wxPoint();
// friend ostream& operator<< <T> ( ostream &stream, const VECTOR2<T>& vector );
};
// ----------------------
// --- Implementation ---
// ----------------------
template<class T> VECTOR2<T>::VECTOR2()
{
x = y = 0.0;
}
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 );
}
template<class T> VECTOR2<T>::VECTOR2( T aX, T aY )
{
x = aX;
y = aY;
}
// Not required at the moment for this class
//template<class T> VECTOR2<T>::~VECTOR2()
//{
// // TODO Auto-generated destructor stub
//}
template<class T> T VECTOR2<T>::EuclideanNorm()
{
return sqrt( ( *this ) * ( *this ) );
}
template<class T> T VECTOR2<T>::Angle()
{
return atan2(y, x);
}
template<class T> VECTOR2<T> VECTOR2<T>::Perpendicular()
{
VECTOR2<T> perpendicular(-y, x);
return perpendicular;
}
/*
template<class T> ostream &operator<<( ostream &aStream, const VECTOR2<T>& aVector )
{
aStream << "[ " << aVector.x << " | " << aVector.y << " ]";
return aStream;
}
*/
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 VECTOR2<T>& aVector )
{
x -= aVector.x;
y -= aVector.y;
return *this;
}
//template<class T> VECTOR2<T>::operator wxPoint()
//{
// wxPoint point;
// point.x = (int) x;
// point.y = (int) y;
// return point;
//}
//
//// Use correct rounding for casting to wxPoint
//template<> VECTOR2<double>::operator wxPoint()
//{
// wxPoint point;
// point.x = point.x >= 0 ? (int) ( x + 0.5 ) : (int) ( x - 0.5 );
// point.y = point.y >= 0 ? (int) ( y + 0.5 ) : (int) ( y - 0.5 );
// return point;
//}
// Use correct rounding for casting double->int
//template<> VECTOR2<double>::operator VECTOR2<int>()
//{
// VECTOR2<int> vector;
// vector.x = vector.x >= 0 ? (int) ( x + 0.5 ) : (int) ( x - 0.5 );
// vector.y = vector.y >= 0 ? (int) ( y + 0.5 ) : (int) ( y - 0.5 );
// return vector;
//}
template<class T> VECTOR2<T> VECTOR2<T>::operator+( const VECTOR2<T>& aVector )
{
return VECTOR2<T> ( x + aVector.x, y + aVector.y );
}
template<class T> VECTOR2<T> VECTOR2<T>::operator-( const VECTOR2<T>& aVector )
{
return VECTOR2<T> ( x - aVector.x, y - aVector.y );
}
template<class T> VECTOR2<T> VECTOR2<T>::operator-()
{
return VECTOR2<T> ( -x, -y );
}
template<class T> T VECTOR2<T>::operator*( const VECTOR2<T>& aVector )
{
return aVector.x * x + aVector.y * y;
}
template<class T> VECTOR2<T> VECTOR2<T>::operator*( const T& aFactor )
{
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> T VECTOR2<T>::operator^( const VECTOR2<T>& aVector )
{
return x * aVector.y - y * aVector.x;
}
template<class T> bool VECTOR2<T>::operator<( const VECTOR2<T>& aVector )
{
// VECTOR2<T> vector( aVector );
// need a specialization for T = int because of overflow:
// return (double( x ) * x + double( y ) * y) < (double( o.x ) * o.x + double( o.y ) * y);
return ( *this * *this ) < ( aVector * aVector );
}
template<class T> bool VECTOR2<T>::operator<=( const VECTOR2<T>& aVector )
{
return ( *this * *this ) <= ( aVector * aVector );
}
template<class T> bool VECTOR2<T>::operator>( const VECTOR2<T>& aVector )
{
return ( *this * *this ) > ( aVector * aVector );
}
template<class T> bool VECTOR2<T>::operator>=( const VECTOR2<T>& aVector )
{
return ( *this * *this ) >= ( aVector * aVector );
}
template<class T> bool const VECTOR2<T>::operator==( VECTOR2<T> const& aVector )
{
return ( aVector.x == x ) && ( aVector.y == y );
}
template<class T> bool const VECTOR2<T>::operator!=( VECTOR2<T> const& aVector )
{
return ( aVector.x != x ) || ( aVector.y != y );
}
/**
* Class BOX2
* is a description of a rectangle in a cartesion coordinate system.
*/
template<class T> class BOX2
{
public:
BOX2() : x(0), y(0), width(0), height(0) {}
BOX2( T aX, T aY, T aWidth, T aHeight ):
x( aX ), y( aY ), width( aWidth ), height( aHeight )
{}
BOX2( const VECTOR2<T>& aPos, const VECTOR2<T>& aSize ) :
x( aPos.x ), y( aPos.y ), width( aSize.x ), height( aSize.y )
{}
BOX2( const wxPoint& aPos, const wxSize& aSize ) :
x( aPos.x ), y( aPos.y ), width( aSize.x ), height( aSize.y )
{}
/*
BOX2( const EDA_RECT& aRect ):
x( aRect.x ), y( aRect.y ), width( aRect.width ), height( aRect.height )
{}
*/
/// Constructor with a wxPoint as argument?
VECTOR2<T> GetSize() const { return VECTOR2<T> ( width, height ); }
VECTOR2<T> GetPosition() const { return VECTOR2<T> ( x, y ); }
T GetLeft() const { return x; }
void SetLeft( T n ) { width += x - n; x = n; }
void MoveLeftTo( T n ) { x = n; }
T GetTop() const { return y; }
void SetTop( T n ) { height += y - n; y = n; }
void MoveTopTo( T n ) { y = n; }
T GetBottom() const { return y + height; }
void SetBottom( T n ) { height += n - ( y + height ); }
void MoveBottomTo( T n ) { y = n - height; }
T GetRight() const { return x + width; }
void SetRight( T n ) { width += n - ( x + width ); }
void MoveRightTo( T n ) { x = n - width; }
VECTOR2<T> GetLeftTop() const { return VECTOR2<T>( x , y ); }
void SetLeftTop( const VECTOR2<T>& pt ) { width += x - pt.x; height += y - pt.y; x = pt.x; y = pt.y; }
void MoveLeftTopTo( const VECTOR2<T> &pt ) { x = pt.x; y = pt.y; }
VECTOR2<T> GetLeftBottom() const { return VECTOR2<T>( x, y + height ); }
void SetLeftBottom( const VECTOR2<T>& pt ) { width += x - pt.x; height += pt.y - (y + height); x = pt.x; }
void MoveLeftBottomTo( const VECTOR2<T>& pt ) { x = pt.x; y = pt.y - height; }
VECTOR2<T> GetRightTop() const { return VECTOR2<T>( x + width, y ); }
void SetRightTop( const VECTOR2<T>& pt ) { width += pt.x - ( x + width ); height += y - pt.y; y = pt.y; }
void MoveRightTopTo( const VECTOR2<T>& pt ) { x = pt.x - width; y = pt.y; }
VECTOR2<T> GetRightBottom() const { return VECTOR2<T>( x + width, y + height ); }
void SetRightBottom( const VECTOR2<T>& pt ) { width += pt.x - ( x + width ); height += pt.y - ( y + height); }
void MoveRightBottomTo( const VECTOR2<T>& pt ) { x = pt.x - width; y = pt.y - height; }
VECTOR2<T> GetCentre() const { return VECTOR2<T>( x + width/2, y + height/2 ); }
void SetCentre( const VECTOR2<T>& pt ) { MoveCentreTo( pt ); }
void MoveCentreTo( const VECTOR2<T>& pt ) { x += pt.x - (x + width/2), y += pt.y - (y + height/2); }
/**
* Function Normalize
* ensures that the height ant width are positive.
*/
void Normalize()
{
if( height < 0 )
{
height = -height;
y -= height;
}
if( width < 0 )
{
width = -width;
x -= width;
}
}
T x, y, width, height;
};
typedef VECTOR2<double> DPOINT;
typedef DPOINT DSIZE;
typedef BOX2<double> DBOX;
#endif // VECTOR2D_H_