415 lines
11 KiB
C++
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_
|