#pragma once #include #define zxIsEqual(x, y, eps) ((x - y) < (eps) && (x - y) > (-eps)) template class ZxInterval { public: inline ZxInterval(); inline ZxInterval(const T &start, const T &stop); inline virtual ~ZxInterval(); inline ZxInterval &operator=(const ZxInterval&); inline virtual ZxInterval* clone() const; inline bool isUdf() const; inline void set(const T &start, const T &stop); inline bool isEqual(const ZxInterval &i, const T &eps) const; inline bool operator==(const ZxInterval&) const; inline bool operator!=(const ZxInterval&) const; inline ZxInterval operator+(const ZxInterval&) const; inline ZxInterval &operator+=(const ZxInterval&); template inline const ZxInterval &setFrom(const ZxInterval&); 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; template inline int getIndex(const X&, const T &step) const; template inline float getfIndex(const X&, const T &step) const; template inline int nearestIndex(const X &x, const T &step) const; template inline void limitTo(const ZxInterval &i) { start = i.limitValue(start); stop = i.limitValue(stop); } template inline X limitValue(const X&) const; template inline bool overlaps(const ZxInterval&, bool allrev = true) const; template inline bool includes(const X&, bool allowrev = true) const; template inline float pos(X val, bool limit = true, bool allowrev = true) const; /*!< returns a value between 0 and 1 if val is between start and stop. */ inline void include(const T&, bool allowrev = true); inline void include(const ZxInterval&, bool allowrev = true); inline virtual void sort(bool asc = true); T start; T stop; inline bool isRev() const; inline virtual bool hasStep() const; }; template inline ZxInterval &ZxInterval::operator=(const ZxInterval &intv) { start = intv.start; stop = intv.stop; return *this; } template template inline int ZxInterval::nearestIndex(const X &x, const T &step) const { int nr = getIndex(x, step); const T atindex = atIndex(nr, step); const float reldiff = (float)(x-atindex)/step; if (reldiff>=0.5) return nr+1; else if (reldiff<=-0.5) return nr-1; return nr; } template inline ZxInterval::ZxInterval() { start = 0; stop = 0; } template inline ZxInterval::ZxInterval(const T &t1, const T &t2) { start = t1; stop = t2; } template inline ZxInterval::~ZxInterval() {} template inline bool ZxInterval::isUdf() const { return zxIsUdf(start) || zxIsUdf(stop); } template inline ZxInterval* ZxInterval::clone() const { return new ZxInterval(*this); } template inline void ZxInterval::set(const T &t1, const T &t2) { start = t1; stop = t2; } template inline bool ZxInterval::isEqual(const ZxInterval &i, const T &eps) const { return zxIsEqual(start, i.start, eps) && zxIsEqual(stop, i.stop, eps); } template inline bool ZxInterval::operator==(const ZxInterval &i) const { return start == i.start && stop == i.stop; } template inline bool ZxInterval::operator!=(const ZxInterval &i) const { return ! (i == *this); } template inline ZxInterval ZxInterval::operator+(const ZxInterval &i) const { return ZxInterval(start+i.start, stop+i.stop); } template inline ZxInterval &ZxInterval::operator+=(const ZxInterval &i) { start += i.start; stop += i.stop; return *this; } template template inline const ZxInterval &ZxInterval::setFrom(const ZxInterval &i) { start = (T) i.start; stop = (T) i.stop; return *this; } template inline T ZxInterval::width(bool allowrev) const { return allowrev && isRev()? start - stop : stop - start; } template inline T ZxInterval::center() const { return (start+stop)/2; } template inline void ZxInterval::shift(const T &len) { start += len; stop += len; } template inline void ZxInterval::widen(const T &len, bool allowrev) { if (allowrev && isRev()) { start += len; stop -= len; } else { start -= len; stop += len; } } template inline void ZxInterval::scale(const T &factor) { start *= factor; stop *= factor; } template template inline bool ZxInterval::includes(const X &t, bool allowrev) const { return allowrev && isRev() ? t >= stop && start >= t : t >= start && stop >= t; } template template inline float ZxInterval::pos(X val, bool limit, bool allowrev) const { float res = allowrev && isRev() ? (val-stop)/(start-stop) : (val-start)/(stop-start); if (limit) { if (res<0) res = 0; else if (res>1) res = 1; } return res; } template template inline bool ZxInterval::overlaps(const ZxInterval &t, bool allowrev) const { return includes(t.start, allowrev) || includes(t.stop, allowrev) || t.includes(start, allowrev) || t.includes(stop, allowrev); } template inline void ZxInterval::include(const T &i, bool allowrev) { if (allowrev && isRev()) { if (stop>i) stop=i; if (starti) start=i; if (stop inline void ZxInterval::include(const ZxInterval &i, bool allowrev) { include(i.start, allowrev); include(i.stop, allowrev); } template inline T ZxInterval::atIndex(int idx, const T &step) const { return start + step * idx; } template template inline int ZxInterval::getIndex(const X &t, const T &step) const { return (int)((t - start) / step); } template template inline float ZxInterval::getfIndex(const X &t, const T &step) const { return (((float)t - start) / step); } template template inline X ZxInterval::limitValue(const X &t) const { const bool isrev = isRev(); if ((!isrev&&t>stop) || (isrev&&tstart)) return start; return t; } template inline void ZxInterval::sort(bool asc) { if ((asc && stop inline bool ZxInterval::hasStep() const { return false; }