You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
457 lines
11 KiB
C++
457 lines
11 KiB
C++
|
|
#ifndef INTERVAL_H
|
|
#define INTERVAL_H
|
|
|
|
namespace NSet
|
|
{
|
|
|
|
#define mIsEqual(x,y,eps) ( (x-y) < (eps) && (x-y) > (-eps) )
|
|
#define mIsZero(x, eps) ( (x) < (eps) && (x) > (-eps) )
|
|
|
|
//!\brief interval of values.
|
|
//Note that start does not need to be lower than stop. That's why there is a sort() method.
|
|
|
|
template <class T>
|
|
class TInterval
|
|
{
|
|
public:
|
|
inline TInterval();
|
|
inline TInterval(const T& start,const T& stop);
|
|
inline TInterval(const TInterval<T>& ti){ start=ti.start; stop=ti.stop; }
|
|
|
|
inline TInterval<T>& operator=(const TInterval<T>&);
|
|
inline bool operator==(const TInterval<T>&) const;
|
|
inline bool operator!=(const TInterval<T>&) const;
|
|
inline TInterval<T> operator+(const TInterval<T>&) const;
|
|
inline TInterval<T>& operator+=(const TInterval<T>&);
|
|
|
|
inline
|
|
virtual TInterval<T>* clone() const;
|
|
|
|
inline void set(const T& start,const T& stop);
|
|
inline bool isEqual(const TInterval<T>& i,const T& eps) const;
|
|
|
|
inline T width(bool allowrev=true) const;
|
|
inline virtual T center() const;
|
|
inline void shift(const T& len);
|
|
inline void widen(const T& len,bool allowrev=true);
|
|
inline virtual void scale(const T&);
|
|
|
|
inline T atIndex(int,const T& step) const;
|
|
|
|
inline bool isIncludes(const T&, bool allowrev=true ) const;
|
|
inline void include(const T&, bool allowrev=true);
|
|
inline void include(const TInterval<T>&,bool allowrev=true);
|
|
|
|
virtual void sort( bool asc=true );
|
|
|
|
inline bool isRev() const { return start > stop; }
|
|
virtual bool hasStep() const { return false; }
|
|
|
|
inline void Swap( T& a, T& b ) { T tmp = a; a = b; b = tmp; }
|
|
|
|
public:
|
|
T start;
|
|
T stop;
|
|
};
|
|
|
|
|
|
typedef TInterval<int> SampleGate;
|
|
typedef TInterval<float> ZGate;
|
|
|
|
template <class T>
|
|
inline void WINAPI Swap( T& a, T& b ) { T tmp = a; a = b; b = tmp; }
|
|
|
|
|
|
/*!\brief TInterval with step. */
|
|
|
|
template <class T>
|
|
class TIntervalStep : public TInterval<T>
|
|
{
|
|
public:
|
|
|
|
inline TIntervalStep();
|
|
inline TIntervalStep(const T& start,const T& stop, const T& step);
|
|
inline TIntervalStep(const TInterval<T>&);
|
|
inline TIntervalStep( const TIntervalStep<T>& si ): TInterval<T>(si), step(si.step) {}
|
|
|
|
inline TIntervalStep<T>& operator=(const TInterval<T>&);
|
|
inline bool operator==(const TIntervalStep<T>&) const;
|
|
inline bool operator!=(const TIntervalStep<T>&) const;
|
|
|
|
inline void getString(char* str) const;
|
|
inline void setString(char*);
|
|
|
|
inline
|
|
virtual TInterval<T>* clone() const;
|
|
inline void set(const T& start,const T& stop,const T& step);
|
|
|
|
inline bool isEqual(const TIntervalStep<T>& i,const T& eps) const;
|
|
inline T atIndex(int) const;
|
|
|
|
inline void Normalise(); //!< Makes sure start<stop and steps are non-zero
|
|
|
|
inline int getIndex( const double& t ) const;
|
|
inline int nearestIndex( const double& t ) const;
|
|
inline T snap( const double& t ) const;
|
|
|
|
inline int nrSteps() const;
|
|
inline float nrfSteps() const;
|
|
virtual inline void sort(bool asc=true);
|
|
inline void scale(const T&);
|
|
|
|
inline bool isCompatible(const TIntervalStep<T>&, float eps=mDefEps) const;
|
|
/*!< epsilon refers to the steps, i.e eps=0.1 allows b to be 0.1 steps apart.*/
|
|
inline T snapStep(const T& inpstep) const;
|
|
/*!<Snaps inpstep to a positive multiple of step. */
|
|
|
|
T step;
|
|
|
|
};
|
|
|
|
///////////////// ---------------- TInterval ---------------------///////////////////////////////////
|
|
|
|
template <class T>
|
|
inline TInterval<T>& TInterval<T>::operator=( const TInterval<T>& intv )
|
|
{
|
|
start = intv.start;
|
|
stop = intv.stop;
|
|
return *this;
|
|
}
|
|
|
|
|
|
template <class T> inline TInterval<T>::TInterval()
|
|
{
|
|
start = 0; stop = 0;
|
|
}
|
|
|
|
|
|
template <class T> inline TInterval<T>::TInterval( const T& t1, const T& t2 )
|
|
{
|
|
start = t1; stop = t2;
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
TInterval<T>* TInterval<T>::clone() const
|
|
{
|
|
return new TInterval<T>( *this );
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
void TInterval<T>::set( const T& t1, const T& t2 )
|
|
{
|
|
start = t1; stop = t2;
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
bool TInterval<T>::isEqual( const TInterval<T>& i, const T& eps ) const
|
|
{
|
|
return mIsEqual(start,i.start,eps) && mIsEqual(stop,i.stop,eps);
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
bool TInterval<T>::operator==( const TInterval<T>& i ) const
|
|
{
|
|
return start == i.start && stop == i.stop;
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
bool TInterval<T>::operator!=( const TInterval<T>& i ) const
|
|
{
|
|
return ! (i == *this);
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
TInterval<T> TInterval<T>::operator+( const TInterval<T>& i ) const
|
|
{
|
|
return TInterval<T>(start+i.start, stop+i.stop);
|
|
}
|
|
|
|
template <class T> inline
|
|
TInterval<T>& TInterval<T>::operator+=( const TInterval<T>& i )
|
|
{
|
|
start += i.start; stop += i.stop; return *this;
|
|
}
|
|
|
|
template <class T> inline
|
|
T TInterval<T>::width( bool allowrev ) const
|
|
{ return allowrev && isRev() ? start - stop : stop - start; }
|
|
|
|
|
|
template <class T> inline
|
|
T TInterval<T>::center() const
|
|
{
|
|
return (start+stop)/2;
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
void TInterval<T>::shift( const T& len )
|
|
{
|
|
start += len;
|
|
stop += len;
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
void TInterval<T>::widen( const T& len, bool allowrev )
|
|
{
|
|
if ( allowrev && isRev() )
|
|
{
|
|
start += len;
|
|
stop -= len;
|
|
}
|
|
else
|
|
{
|
|
start -= len;
|
|
stop += len;
|
|
}
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
void TInterval<T>::scale( const T& factor )
|
|
{ start *= factor; stop *= factor; }
|
|
|
|
|
|
template <class T> inline
|
|
bool TInterval<T>::isIncludes( const T& t, bool allowrev ) const
|
|
{
|
|
return allowrev && isRev() ? t>=stop && start>=t : t>=start && stop>=t;
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
void TInterval<T>::include( const T& i, bool allowrev )
|
|
{
|
|
if ( allowrev && isRev() )
|
|
{
|
|
if ( stop >i ) stop=i;
|
|
if ( start<i ) start=i;
|
|
}
|
|
else
|
|
{
|
|
if ( start>i ) start=i;
|
|
if ( stop <i ) stop=i;
|
|
}
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
void TInterval<T>::include( const TInterval<T>& i, bool allowrev )
|
|
{ include( i.start, allowrev ); include( i.stop, allowrev ); }
|
|
|
|
|
|
template <class T> inline
|
|
T TInterval<T>::atIndex( int idx, const T& step ) const
|
|
{ return start + step * idx; }
|
|
|
|
template <class T>
|
|
void TInterval<T>::sort( bool asc )
|
|
{
|
|
if ( (asc && stop<start) || (!asc && start<stop) )
|
|
Swap(start,stop);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////// ---------------- TIntervalStep --------------------//////////////////////////////////
|
|
|
|
template <class T>
|
|
TIntervalStep<T>::TIntervalStep()
|
|
{ step = 1; }
|
|
|
|
|
|
template <class T>
|
|
TIntervalStep<T>::TIntervalStep( const T& t1, const T& t2, const T& t3 )
|
|
: TInterval<T>(t1,t2)
|
|
{ step = t3; }
|
|
|
|
|
|
template <class T>
|
|
TIntervalStep<T>::TIntervalStep( const TInterval<T>& intv )
|
|
: TInterval<T>(intv)
|
|
{
|
|
step = 1;
|
|
}
|
|
|
|
template <class T>
|
|
void TIntervalStep<T>::getString(char* str) const
|
|
{
|
|
if ( !str ) return;
|
|
double xx[3];
|
|
xx[0] = this->start;
|
|
xx[1] = this->stop;
|
|
xx[2] = step;
|
|
AfxGetBaseFunction()->PrintXYZ(str, xx, 3, ' ');
|
|
}
|
|
|
|
template <class T>
|
|
void TIntervalStep<T>::setString(char* str)
|
|
{
|
|
if ( !str ) return;
|
|
double xx[3];
|
|
sscanf_s( str, _T("%lf %lf %lf"), xx, xx+1, xx+2 );
|
|
start = (T)xx[0];
|
|
stop = (T)xx[1];
|
|
step = (T)xx[2];
|
|
}
|
|
|
|
template <class T> inline
|
|
TInterval<T>* TIntervalStep<T>::clone() const
|
|
{ return new TIntervalStep<T>( *this ); }
|
|
|
|
|
|
template <class T> inline
|
|
void TIntervalStep<T>::set( const T& t1, const T& t2, const T& t3 )
|
|
{ TInterval<T>::set( t1, t2 ); step = t3; }
|
|
|
|
template <class T> inline
|
|
bool TIntervalStep<T>::isEqual( const TIntervalStep<T>& i, const T& eps ) const
|
|
{ return TInterval<T>::isEqual(i,eps) && mIsEqual(step,i.step,eps); }
|
|
|
|
template <class T> inline
|
|
TIntervalStep<T>& TIntervalStep<T>::operator=(const TInterval<T>& ti)
|
|
{
|
|
start = ti.start;
|
|
stop = ti.stop;
|
|
return *this;
|
|
}
|
|
|
|
template <class T> inline
|
|
bool TIntervalStep<T>::operator==( const TIntervalStep<T>& i ) const
|
|
{ return TInterval<T>::operator==(i) && i.step==step; }
|
|
|
|
|
|
template <class T> inline
|
|
bool TIntervalStep<T>::operator!=( const TIntervalStep<T>& i ) const
|
|
{ return ! (i == *this); }
|
|
|
|
|
|
template <class T> inline
|
|
T TIntervalStep<T>::atIndex( int idx ) const
|
|
{ return TInterval<T>::atIndex(idx,step); }
|
|
|
|
template <class T>
|
|
int TIntervalStep<T>::getIndex( const double& t ) const
|
|
{ return (int)(( t - start ) / step); }
|
|
|
|
|
|
template <class T>
|
|
int TIntervalStep<T>::nearestIndex( const double& t ) const
|
|
{
|
|
int nr = getIndex(t);
|
|
const T atindex = atIndex(nr);
|
|
double reldiff = (t-atindex)/step;
|
|
|
|
if ( reldiff>=0.5 ) return nr+1;
|
|
else if ( reldiff<=-0.5 ) return nr-1;
|
|
return nr;
|
|
}
|
|
|
|
template <class T> inline
|
|
T TIntervalStep<T>::snap( const double& t ) const
|
|
{ return atIndex( nearestIndex( t ) ); }
|
|
|
|
template <class T> inline
|
|
void TIntervalStep<T>::sort( bool asc )
|
|
{
|
|
TInterval<T>::sort(asc);
|
|
if ( (asc && step < 0) || (!asc && step > 0) )
|
|
step = -step;
|
|
}
|
|
|
|
template <class T> inline
|
|
void TIntervalStep<T>::Normalise() //!< Makes sure start<stop and steps are non-zero
|
|
{
|
|
sort();
|
|
if(step == 0) step = 1;
|
|
}
|
|
|
|
template <class T> inline
|
|
void TIntervalStep<T>::scale( const T& factor )
|
|
{
|
|
TInterval<T>::scale( factor );
|
|
step *= factor;
|
|
}
|
|
|
|
template <class T> inline
|
|
T TIntervalStep<T>::snapStep( const T& inputstep ) const
|
|
{
|
|
const float relstep = (float) inputstep/step;
|
|
int nrsteps = AfxGetBaseFunction()->FloatToLong(relstep);
|
|
if ( nrsteps<1 ) nrsteps = 1;
|
|
return step*nrsteps;
|
|
}
|
|
|
|
|
|
template <class T> inline
|
|
float TIntervalStep<T>::nrfSteps() const
|
|
{
|
|
const float w = (float)TInterval<T>::width( true );
|
|
return w/step;
|
|
}
|
|
|
|
|
|
template <class T>
|
|
inline int TIntervalStep<T>::nrSteps() const
|
|
{
|
|
if ( !step ) return 0;
|
|
int ret = (((int)this->start) - this->stop) / step;
|
|
return ret < 0 ? -ret : ret;
|
|
}
|
|
|
|
#define mDefFNrSteps(typ,eps) \
|
|
template <> \
|
|
inline int TIntervalStep<typ>::nrSteps() const \
|
|
{ \
|
|
if ( !step ) return 0; \
|
|
typ ns = ( (start > stop ? start : stop) \
|
|
- (start > stop ? stop : start) ) \
|
|
/ (step > 0 ? step : -step); \
|
|
return (int)(ns * (1. + eps)); \
|
|
}
|
|
|
|
mDefFNrSteps(float,1e-4)
|
|
mDefFNrSteps(double,1e-8)
|
|
|
|
template <class T>
|
|
inline bool TIntervalStep<T>::isCompatible( const TIntervalStep<T>& b, float ) const
|
|
{
|
|
if ( step>b.step || b.step%step )
|
|
return false;
|
|
|
|
// const T diff = static_cast<const TInterval<T>*>(this)->start - b.start;
|
|
const T diff = this->start - b.start;
|
|
return !(diff%step);
|
|
}
|
|
|
|
|
|
#define mDefFltisCompat(typ) \
|
|
template <> \
|
|
inline bool TIntervalStep<typ>::isCompatible( const TIntervalStep<typ>& b, float eps ) const \
|
|
{ \
|
|
if ( !mIsEqual(step,b.step,eps) ) return false; \
|
|
\
|
|
typ nrsteps = (start - b.start) / step; \
|
|
int nrstepsi = AfxGetBaseFunction()->FloatToLong( nrsteps ); \
|
|
typ diff = nrsteps - nrstepsi; \
|
|
return ( (diff) < (eps) && (diff) > (-eps) ); \
|
|
}
|
|
|
|
mDefFltisCompat(float)
|
|
mDefFltisCompat(double)
|
|
|
|
|
|
}//namespace
|
|
|
|
using namespace NSet;
|
|
|
|
#endif //INTERVAL_H
|