You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.2 KiB
106 lines
3.2 KiB
/* BEGIN COPYRIGHT
|
|
*
|
|
* This file is part of Noted.
|
|
*
|
|
* Copyright ©2011, 2012, Lancaster Logic Response Limited.
|
|
*
|
|
* Noted 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.
|
|
*
|
|
* Noted 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 Noted. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <type_traits>
|
|
#include <cmath>
|
|
|
|
#undef foreach
|
|
#define foreach BOOST_FOREACH
|
|
|
|
namespace lb
|
|
{
|
|
|
|
template <class T>
|
|
static T graphParameters(T _min, T _max, unsigned _divisions, T* o_from = 0, T* o_delta = 0, bool _forceMinor = false, T _divisor = 1)
|
|
{
|
|
T uMin = _min / _divisor;
|
|
T uMax = _max / _divisor;
|
|
if (uMax == uMin || !_divisions)
|
|
{
|
|
if (o_delta && o_from)
|
|
{
|
|
*o_from = 0;
|
|
*o_delta = 1;
|
|
}
|
|
return 1;
|
|
}
|
|
long double l10 = std::log10((uMax - uMin) / T(_divisions) * 5.5f);
|
|
long double mt = std::pow(10.f, l10 - std::floor(l10));
|
|
long double ep = std::pow(10.f, std::floor(l10));
|
|
T inc = _forceMinor
|
|
? ((mt > 6.f) ? ep / 2.f : (mt > 3.f) ? ep / 5.f : (mt > 1.2f) ? ep / 10.f : ep / 20.f)
|
|
: ((mt > 6.f) ? ep * 2.f : (mt > 3.f) ? ep : (mt > 1.2f) ? ep / 2.f : ep / 5.f);
|
|
if (inc == 0)
|
|
inc = 1;
|
|
if (o_delta && o_from)
|
|
{
|
|
(*o_from) = std::floor(uMin / inc) * inc * _divisor;
|
|
(*o_delta) = (std::ceil(uMax / inc) - std::floor(uMin / inc)) * inc * _divisor;
|
|
}
|
|
else if (o_from)
|
|
{
|
|
(*o_from) = std::ceil(uMin / inc) * inc * _divisor;
|
|
}
|
|
return inc * _divisor;
|
|
}
|
|
|
|
struct GraphParametersForceMinor { GraphParametersForceMinor() {} };
|
|
static const GraphParametersForceMinor ForceMinor;
|
|
|
|
template <class T>
|
|
struct GraphParameters
|
|
{
|
|
inline GraphParameters(std::pair<T, T> _range, unsigned _divisions)
|
|
{
|
|
incr = graphParameters(_range.first, _range.second, _divisions, &from, &delta, false);
|
|
to = from + delta;
|
|
}
|
|
|
|
inline GraphParameters(std::pair<T, T> _range, unsigned _divisions, GraphParametersForceMinor)
|
|
{
|
|
incr = graphParameters(_range.first, _range.second, _divisions, &from, &delta, true);
|
|
to = from + delta;
|
|
}
|
|
|
|
inline GraphParameters(std::pair<T, T> _range, unsigned _divisions, T _divisor)
|
|
{
|
|
major = graphParameters(_range.first, _range.second, _divisions, &from, &delta, false, _divisor);
|
|
incr = graphParameters(_range.first, _range.second, _divisions, &from, &delta, true, _divisor);
|
|
to = from + delta;
|
|
}
|
|
|
|
template <class S, class Enable = void>
|
|
struct MajorDeterminor { static bool go(S _s, S _j) { S ip; S fp = std::modf(_s / _j + S(0.5), &ip); return fabs(fabs(fp) - 0.5) < 0.05; } };
|
|
template <class S>
|
|
struct MajorDeterminor<S, typename std::enable_if<std::is_integral<S>::value>::type> { static S go(S _s, S _j) { return _s % _j == 0; } };
|
|
|
|
bool isMajor(T _t) const { return MajorDeterminor<T>::go(_t, major); }
|
|
|
|
T from;
|
|
T delta;
|
|
T major;
|
|
T to;
|
|
T incr;
|
|
};
|
|
|
|
}
|
|
|