Commit d53f6664 authored by Vladimir Ur's avatar Vladimir Ur

New draft for length.h

parent a5a435f1
...@@ -3,661 +3,186 @@ ...@@ -3,661 +3,186 @@
* @file length.h * @file length.h
*/ */
#ifndef UNITS_H_INCLUDED /* sorry it is not styles correctly, i'll work on it further */
#define UNITS_H_INCLUDED 1
#include <math.h> #ifndef LENGTH_H_INCLUDED
#include <wx/gdicmn.h> #define LENGTH_H_INCLUDED 1
/**********************************************/
/*! I'm a physical length */
/**********************************************/
class LENGTH typedef int DEF_LENGTH_VALUE;
{
private: template <typename T = DEF_LENGTH_VALUE, int P = 1> class LENGTH;
enum
{
METER = 1000000000, /* The ONLY constant connecting length to the real world */
};
int m_Units;
/*!
* The only constructor allowing direct input of numeric value
* in internal units. As this is not allowed in public, it's private.
* Length objects elsewhere are created indirectly
* @param units Length in internal units.
*/
LENGTH( int units )
{
m_Units = units;
}
public:
/*!
* Equality comparison of physical lengths.
* @param y length to compare
* @return lengths are equal
*/
bool operator == ( const LENGTH y ) const
{
return m_Units == y.m_Units;
}
/*!
* Non-equality comparison of physical lengths.
* @param y length to compare
* @return lengts are different
*/
bool operator != ( const LENGTH y ) const
{
return m_Units != y.m_Units;
}
/*!
* Order comparison of physical lengths.
* @param y length to compare
* @return one less than another
*/
bool operator < ( const LENGTH y ) const
{
return m_Units < y.m_Units;
}
/*!
* Order comparison of physical lengths.
* @param y length to compare
* @return one greater than another
*/
bool operator > ( const LENGTH y ) const
{
return m_Units > y.m_Units;
}
/*! template <typename T> class LENGTH_UNITS;
* Order comparison of physical lengths.
* @param y length to compare
* @return one less or equal than another
*/
bool operator <= ( const LENGTH y ) const
{
return m_Units <= y.m_Units;
}
/*! template <typename T, int P> struct LENGTH_TRAITS {
* Order comparison of physical lengths. typedef LENGTH<T, P> flat;
* @param y length to compare };
* @return one greater or equal than another
*/
bool operator >= ( const LENGTH y ) const
{
return m_Units >= y.m_Units;
}
/*!
* Sum of two physical lengths. Only another length can be added.
* @param y length to add
* @return result of addition
*/
const LENGTH operator + ( const LENGTH y ) const
{
return LENGTH( m_Units + y.m_Units );
}
/*!
* Add a length inplace
* @param y length to add
* @return result of addition
*/
LENGTH & operator += ( const LENGTH y )
{
m_Units += y.m_Units;
return *this;
}
/*!
* Differece of two physical lengths. Only another length can be subtracted.
* @param y length to subtract
* @return result of subtraction
*/
const LENGTH operator - ( const LENGTH y ) const
{
return LENGTH( m_Units - y.m_Units );
}
/*!
* Subtract a length inplace
* @param y length to add
* @return result of addition
*/
LENGTH & operator -= ( const LENGTH y )
{
m_Units -= y.m_Units;
return *this;
}
/*!
* Negation of length.
* @return length negated
*/
const LENGTH operator - ( void ) const {
return LENGTH( - m_Units );
}
/*!
* Scale length to rational number, given numerator and denominator.
* This is done without overflow or precision loss unlike dealing
* with * / and floating point.
* @param mul numerator, length is multiplied by this value
* @param div denominator. length is divided by this value
* @return scaled length
*/
const LENGTH byRatio ( int mul, int div ) const
{
return LENGTH( ( int )( ( long long ) m_Units * mul / div ) );
}
/*!
* Scale length to rational number inplace.
* @param mul numerator, length is multiplied by this value
* @param div denominator. length is divided by this value
* @return scaled length
*/
LENGTH & setByRatio ( int mul, int div )
{
m_Units = ( int )( ( long long ) m_Units * mul / div );
return *this;
}
/*!
* Multiplies length by integer number.
* @param y factor
* @return scaled length
*/
const LENGTH operator * ( int y ) const
{
return LENGTH( m_Units * y );
}
/*! template <typename T> struct LENGTH_TRAITS<T, 0> {
* Multiply a length inplace typedef T flat;
* @param y factor };
* @return scaled length
*/
LENGTH & operator *= ( int y )
{
m_Units *= y;
return *this;
}
/*! template<typename T, int P> class LENGTH {
* Multiplies length by floating point. friend class LENGTH_UNITS<T>;
* @param y factor friend class LENGTH_TRAITS<T, P>;
* @return scaled length template <typename Y, int R> friend class LENGTH;
*/ protected:
const LENGTH operator * ( double y ) const
{
return LENGTH( ( int )( m_Units * y ) );
}
/*! T m_U;
* Multiply a length inplace LENGTH(T units) : m_U(units) {
* @param y factor
* @return scaled length
*/
LENGTH & operator *= ( double y )
{
m_Units *= y;
return *this;
} }
static T RawValue(const LENGTH<T, P> &x) {
/*! return x.m_U;
* Multiplies integer by length ( like abowe with args swapped ).
* @param x factor
* @param y length
* @return scaled length
*/
const LENGTH friend operator * ( int x, const LENGTH y )
{
return y * x;
} }
static T RawValue(const T& x) {
/*! return x;
* Multiplies floating point by length ( like abowe with args swapped ).
* @param x factor
* @param y length
* @return scaled length
*/
const LENGTH friend operator * ( double x, const LENGTH y )
{
return y * x;
} }
public:
/*! typedef LENGTH<T, P> flat;
* Divides length by integer number. typedef T value_type;
* @param y divider enum {
* @return scaled length dimension = P
*/ };
const LENGTH operator / ( int y ) const LENGTH(const LENGTH <T, P> &orig) : m_U(orig.m_U) {
{
return LENGTH( m_Units / y );
} }
LENGTH( void ) : m_U() {
/*!
* Divide a length inplace
* @param y divider
* @return scaled length
*/
LENGTH & operator /= ( int y )
{
m_Units /= y;
return *this;
} }
/*! static LENGTH<T, P> zero (void) {
* Divides length by floating point. return T(0);
* @param y divider
* @return scaled length
*/
const LENGTH operator / ( double y ) const
{
return LENGTH( ( long long )( m_Units / y ) );
} }
/*! LENGTH<T, P> & operator = (const LENGTH<T, P> & y) {
* Divide a length inplace this->m_U = y.m_U;
* @param y divider
* @return scaled length
*/
LENGTH & operator /= ( double y )
{
m_Units /= y;
return *this; return *this;
} }
template<typename Y>
/*! operator LENGTH<Y, P> (void) {
* Gets ratio of two lengths. return this->m_U;
* It is usable to get number of length units in length by
* division of length by length unit ( See length units below ).
* @param y base length
* @return scaled length
*/
double operator / ( const LENGTH y ) const
{
return ( double ) m_Units / y.m_Units;
} }
/*************************/
/*! /* comparisons and tests */
* Gets integer ( unlike operator / ) ratio of two lengths. /*************************/
* It is usable to get number of length units in length by bool operator ==(const LENGTH <T, P> y) const {
* division of length by length unit ( See length units below ). return m_U == y.m_U;
* @param y base length
* @return scaled length
*/
int idiv( const LENGTH y ) const
{
return ( int )( m_Units / y.m_Units );
} }
bool operator !=(const LENGTH <T, P> y) const {
/*! return m_U != y.m_U;
* Zero.
* @return Zero length
*/
static const LENGTH zero( void )
{
return LENGTH( 0 );
}
/*!
* The metre unit.
* @return One metre length
*/
static const LENGTH metre( void )
{
return LENGTH( METER );
} }
bool operator <(const LENGTH <T, P> y) const {
/*! return m_U < y.m_U;
* The millimetre unit.
* @return One millimetre length
*/
static const LENGTH millimetre( void )
{
return LENGTH( METER/1000 );
} }
bool operator >=(const LENGTH <T, P> y) const {
/*! return m_U >= y.m_U;
* The inch unit.
* @return One inch length
*/
static const LENGTH inch( void )
{
return LENGTH( METER/10000*254 ); // ensure it's done without precision loss
} }
bool operator >(const LENGTH <T, P> y) const {
/*! return m_U > y.m_U;
* The mil unit.
* @return One mil length
*/
static const LENGTH mil( void )
{
return inch()/1000;
} }
bool operator <=(const LENGTH <T, P> y) const {
/*! return m_U <= y.m_U;
* Hypotenuse of a triangle with two given katheti.
* @param y another kathetus
* @return hypothenuse
*/
const LENGTH hypotenuse( LENGTH y ) const
{
return LENGTH ( ( int ) sqrt (
( ( double ) m_Units * m_Units
+ ( double ) y.m_Units * y.m_Units ) ) );
} }
bool operator !( void ) const {
/*! return !m_U;
* Another kathetus of a triangle with given hypothenuse and kathetus.
* @param y kathetus
* @return another kathetus
*/
const LENGTH kathetus( LENGTH y ) const
{
return LENGTH ( ( int ) sqrt (
( ( double ) m_Units * m_Units
- ( double ) y.m_Units * y.m_Units ) ) );
} }
/*************************/
}; /* basic arithmetic */
/*************************/
/**********************************************/ LENGTH<T, P> operator - (void) const {
/*! I'm a point/vector in a physical 2D plane */ return LENGTH<T, P>(-this->m_U);
/**********************************************/
class LENGTH_XY {
private:
LENGTH m_X, m_Y;
public:
/*!
* One given x and y coords of type LENGTH
* @param x coordinate
* @param y coordinate
*/
LENGTH_XY( const LENGTH x, const LENGTH y ) : m_X( x ), m_Y( y )
{
} }
LENGTH<T, P> operator - (const LENGTH<T, P> y) const {
/*! return m_U - y.m_U;
* A point ( or vector ) given x and y multiplies of specified unit.
* Given just for a convenience, you can use ( x*unit, y*unit ) instead.
* @param x coordinate factor
* @param y coordinate factor
* @param unit the unit
*/
LENGTH_XY( int x, int y, const LENGTH unit ) : m_X( unit * x ), m_Y( unit * y )
{
} }
LENGTH<T, P> operator + (const LENGTH<T, P> y) const {
/*! return m_U + y.m_U;
* A point ( or vector ) given wxPoint and unit
* @param x wxPoint
* @param unit the unit
*/
LENGTH_XY( wxPoint x, const LENGTH unit ) : m_X( unit * x.x ), m_Y( unit * x.y )
{
} }
template <int R>
/*! typename LENGTH_TRAITS<T, P + R>::flat operator * (const LENGTH<T, R> &y) const {
* A point ( or vector ) given wxRealPoint and unit return m_U * y.m_U;
* @param x wxRealPoint
* @param unit the unit
*/
LENGTH_XY( wxRealPoint x, const LENGTH unit ) : m_X( unit * x.x ), m_Y( unit * x.y )
{
} }
LENGTH<T, P> operator * (const T &y) const {
/*! return m_U * y;
* x coordinate
* @return x coordinate
*/
const LENGTH x( void ) const
{
return m_X;
} }
LENGTH<T, P> friend operator * (const T &y, const LENGTH<T, P> &x) {
/*! return x.m_U * y;
* y coordinate
* @return y coordinate
*/
const LENGTH y( void ) const
{
return m_Y;
} }
/*! template <int R>
* Absoulte value / length typename LENGTH_TRAITS<T, P - R>::flat operator / (const LENGTH<T, R> &y) const {
* @return absolute value return m_U / y.m_U;
*/
const LENGTH abs( void ) const
{
return m_X.hypotenuse(m_Y);
} }
LENGTH<T, P> operator / (const T &y) const {
/*! return m_U / y;
* Equality comparison of vectors.
* @param y vectors to compare
* @return vectors are equal
*/
bool operator == ( const LENGTH_XY y ) const
{
return m_X == y.m_X && m_Y == y.m_Y;
} }
LENGTH<T, -P> friend operator / (const T &y, const LENGTH<T, P> &x) {
/*! return y / x.m_U;
* Non-equality comparison of vectors.
* @param y vectors to compare
* @return vectors are different
*/
bool operator != ( const LENGTH_XY y ) const
{
return m_X != y.m_X || m_Y != y.m_Y;
} }
/*! friend LENGTH<T, P> sqrt(LENGTH<T, P*2> y) {
* Sum of two vectors ( or a point translated by vector ) return sqrt(y.m_U);
* @param y vector to add
* @return result of addition
*/
const LENGTH_XY operator + ( const LENGTH_XY y ) const
{
return LENGTH_XY( m_X + y.m_X, m_Y + y.m_Y );
} }
friend LENGTH<T, P> cbrt(LENGTH<T, P*3> y) {
/*! return cbrt(y.m_U);
* Translate a vector inplace
* @param y vector to add
* @return result of addition
*/
LENGTH_XY & operator += ( const LENGTH_XY y )
{
m_X += y.m_X;
m_Y += y.m_Y;
return *this;
} }
/*************************/
/*! /* assignment arithmetic */
* Difference of two vectors ( or a point translated by vector in reverse direction ). /*************************/
* @param y vector to subtract LENGTH<T, P>& operator -= (const LENGTH<T, P> y) {
* @return result of subtraction return m_U -= y.m_U;
*/
const LENGTH_XY operator - ( const LENGTH_XY y ) const
{
return LENGTH_XY( m_X - y.m_X, m_Y - y.m_Y );
} }
LENGTH<T, P>& operator += (const LENGTH<T, P> y) {
/*! return m_U += y.m_U;
* Translate a vector inplace in opposite direction
* @param y vector to subtract
* @return result of subtraction
*/
LENGTH_XY & operator -= ( const LENGTH_XY y )
{
m_X -= y.m_X;
m_Y -= y.m_Y;
return *this;
} }
LENGTH<T, P>& operator *= (const T y) {
/*! return m_U *= y;
* Vector with reverse direction.
* @return reverse direction vector
*/
const LENGTH_XY operator - ( void ) const
{
return LENGTH_XY( - m_X, - m_Y );
} }
LENGTH<T, P>& operator /= (const T y) {
/*! return m_U /= y;
* Scale vector to rational number, given numerator and denominator.
* This is done without overflow or precision loss unlike dealing
* with * / and floating point.
* @param mul numerator ( length is multiplied by this value )
* @param div denominator ( length is divided by this value )
* @return scaled vector
*/
const LENGTH_XY byRatio ( int mul, int div )
{
return LENGTH_XY( m_X.byRatio( mul, div ), m_Y.byRatio( mul, div ) );
} }
/*************************/
/* more arithmetic */
/*************************/
};
/*! template <typename T = DEF_LENGTH_VALUE> class LENGTH_UNITS {
* Scale vector to rational number, inplace (like operator *=). protected:
* @param mul numerator ( length is multiplied by this value ) enum
* @param div denominator ( length is divided by this value )
* @return scaled vector
*/
LENGTH_XY & setByRatio ( int mul, int div )
{ {
m_X.setByRatio( mul, div ); METRE = 1000000000, /* The ONLY constant connecting length to the real world */
m_Y.setByRatio( mul, div );
return *this;
}
/*! INCH = METRE / 10000 * 254
* Multiplies vector length by integer number. };
* @param y factor public:
* @return scaled vector static LENGTH<T, 1> metre( void ) {
*/ return T(METRE);
const LENGTH_XY operator * ( int y ) const
{
return LENGTH_XY( m_X * y, m_Y * y );
} }
static LENGTH<T, 1> decimetre( void ) {
/*! return T(METRE / 10);
* Multiply a vector inplace
* @param y factor
* @return scaled vector
*/
LENGTH_XY & operator *= ( int y )
{
m_X *= y;
m_Y *= y;
return *this;
} }
static LENGTH<T, 1> centimetre( void ) {
/*! return T(METRE / 100);
* Multiplies vector length by floating point number.
* @param y factor
* @return scaled length
*/
const LENGTH_XY operator * ( double y ) const
{
return LENGTH_XY( m_X * y, m_Y * y );
} }
static LENGTH<T, 1> millimetre( void ) {
/*! return T(METRE / 1000);
* Multiply a vector inplace
* @param y factor
* @return scaled vector
*/
LENGTH_XY & operator *= ( double y )
{
m_X *= y;
m_Y *= y;
return *this;
} }
static LENGTH<T, 1> micrometre( void ) {
/*! return T(METRE / 1000000);
* Divides vector length by integer number.
* @param y divider
* @return scaled vector
*/
const LENGTH_XY operator / ( int y ) const
{
return LENGTH_XY( m_X / y, m_Y / y );
} }
static LENGTH<T, 1> foot( void ) { /* do not think this will ever need */
/*! return T(INCH * 12);
* Divide a vector inplace
* @param y divider
* @return scaled vector
*/
LENGTH_XY & operator /= ( int y )
{
m_X /= y;
m_Y /= y;
return *this;
} }
static LENGTH<T, 1> inch( void ) {
/*! return T(INCH);
* Divides vector length by floating point number.
* @param y divider
* @return scaled vector
*/
const LENGTH_XY operator / ( double y ) const
{
return LENGTH_XY( m_X / y, m_Y / y );
} }
static LENGTH<T, 1> mil( void ) {
/*! return T(INCH / 1000);
* Divide a vector inplace
* @param y divider
* @return scaled vector
*/
LENGTH_XY & operator /= ( double y )
{
m_X /= y;
m_Y /= y;
return *this;
} }
};
/*! /* shortcut */
* Outputs wxPoint in specified scale. template <typename T, int D> class LENGTH_UNITS<LENGTH<T, D> >: public LENGTH_UNITS<T> {
* @param y scale };
* @return wxPoint
*/
const wxPoint toWxPoint ( LENGTH y ) const
{
return wxPoint( m_X.idiv( y ), m_Y.idiv( y ) );
}
/*! /* TODO: argument promotion (but is this need? explicit casts would be enough) */
* Outputs wxRealPoint in specified scale.
* @param y scale
* @return wxPoint
*/
const wxRealPoint toWxRealPoint ( LENGTH y ) const
{
return wxRealPoint( m_X / y, m_Y / y );
}
/*!
* Rotates vector 90 degrees ( X axis towards Y )
* @return rotated
*/
const LENGTH_XY rot90 ( void ) const
{
return LENGTH_XY( m_Y, -m_X );
}
};
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment