10#include "qwt_scale_engine.h" 
   12#include "qwt_interval.h" 
   13#include "qwt_transform.h" 
   19static inline double qwtLog( 
double base, 
double value )
 
   21    return std::log( value ) / std::log( base );
 
   27        qwtLog( base, interval.
maxValue() ) );
 
   33        std::pow( base, interval.
maxValue() ) );
 
   39static double qwtStepSize( 
double intervalSize, 
int maxSteps, uint base )
 
   41    const double minStep =
 
   47        const int numTicks = qwtCeil( qAbs( intervalSize / minStep ) ) - 1;
 
   50        if ( qwtFuzzyCompare( ( numTicks + 1 ) * qAbs( minStep ),
 
   51            qAbs( intervalSize ), intervalSize ) > 0 )
 
   54            return 0.5 * intervalSize;
 
   63static double qwtStepSize( 
double intervalSize, 
int maxSteps, uint base )
 
   70        for ( 
int numSteps = maxSteps; numSteps > 1; numSteps-- )
 
   72            const double stepSize = intervalSize / numSteps;
 
   74            const double p = std::floor( std::log( stepSize ) / std::log( base ) );
 
   75            const double fraction = std::pow( base, p );
 
   77            for ( uint n = base; n > 1; n /= 2 )
 
   79                if ( qFuzzyCompare( stepSize, n * fraction ) )
 
   82                if ( n == 3 && ( base % 2 ) == 0 )
 
   84                    if ( qFuzzyCompare( stepSize, 2 * fraction ) )
 
   91    return intervalSize * 0.5;
 
   96static const double _eps = 1.0e-6;
 
  109    double intervalSize )
 
  111    const double eps = _eps * intervalSize;
 
  113    value = ( value - eps ) / intervalSize;
 
  114    return std::ceil( value ) * intervalSize;
 
 
  128    const double eps = _eps * intervalSize;
 
  130    value = ( value + eps ) / intervalSize;
 
  131    return std::floor( value ) * intervalSize;
 
 
  145    if ( numSteps == 0.0 || intervalSize == 0.0 )
 
  148    return ( intervalSize - ( _eps * intervalSize ) ) / numSteps;
 
 
  161    double intervalSize, 
int numSteps, uint base )
 
  170    const double lx = qwtLog( base, std::fabs( v ) );
 
  171    const double p = std::floor( lx );
 
  173    const double fraction = std::pow( base, lx - p );
 
  176    while ( ( n > 1 ) && ( fraction <= n / 2 ) )
 
  179    double stepSize = n * std::pow( base, p );
 
  181        stepSize = -stepSize;
 
 
  186class QwtScaleEngine::PrivateData
 
  193        referenceValue( 0.0 ),
 
  209    double referenceValue;
 
  224    m_data = 
new PrivateData;
 
 
  250    if ( transform != m_data->transform )
 
  252        delete m_data->transform;
 
  253        m_data->transform = transform;
 
 
  268    if ( m_data->transform )
 
  269        transform = m_data->transform->
copy();
 
 
  282    return m_data->lowerMargin;
 
 
  293    return m_data->upperMargin;
 
 
  314    m_data->lowerMargin = qwtMaxF( lower, 0.0 );
 
  315    m_data->upperMargin = qwtMaxF( upper, 0.0 );
 
 
  327    double intervalSize, 
int numSteps )
 const 
  330        intervalSize, numSteps, m_data->base );
 
 
  347    if ( qwtFuzzyCompare( value, interval.
minValue(), interval.
width() ) < 0 )
 
  350    if ( qwtFuzzyCompare( value, interval.
maxValue(), interval.
width() ) > 0 )
 
 
  367    if ( !interval.
isValid() || ticks.count() == 0 )
 
  370    if ( 
contains( interval, ticks.first() )
 
  371        && 
contains( interval, ticks.last() ) )
 
  377    for ( 
int i = 0; i < ticks.count(); i++ )
 
  379        if ( 
contains( interval, ticks[i] ) )
 
  380            strippedTicks += ticks[i];
 
  382    return strippedTicks;
 
 
  397    const double delta = ( value == 0.0 ) ? 0.5 : qAbs( 0.5 * value );
 
  398    const double max = std::numeric_limits< double >::max();
 
  400    if ( max - delta < value )
 
  403    if ( -max + delta > value )
 
  406    return QwtInterval( value - delta, value + delta );
 
 
  420        m_data->attributes |= attribute;
 
  422        m_data->attributes &= ~attribute;
 
 
  433    return ( m_data->attributes & attribute );
 
 
  453    return m_data->attributes;
 
 
  476    return m_data->referenceValue;
 
 
  493    m_data->base = qMax( 
base, 2U );
 
 
  532    double& x1, 
double& x2, 
double& stepSize )
 const 
  546    if ( interval.
width() == 0.0 )
 
  550        interval.
width(), qMax( maxNumSteps, 1 ), 
base() );
 
  553        interval = 
align( interval, stepSize );
 
  561        stepSize = -stepSize;
 
 
  578    int maxMajorSteps, 
int maxMinorSteps, 
double stepSize )
 const 
  582    if ( interval.
widthL() > std::numeric_limits< double >::max() )
 
  584        qWarning() << 
"QwtLinearScaleEngine::divideScale: overflow";
 
  588    if ( interval.
width() <= 0 )
 
  591    stepSize = qAbs( stepSize );
 
  592    if ( stepSize == 0.0 )
 
  594        if ( maxMajorSteps < 1 )
 
  598            interval.
width(), maxMajorSteps, 
base() );
 
  603    if ( stepSize != 0.0 )
 
  606        buildTicks( interval, stepSize, maxMinorSteps, ticks );
 
 
  628    const QwtInterval& interval, 
double stepSize, 
int maxMinorSteps,
 
  636    if ( maxMinorSteps > 0 )
 
  644        ticks[i] = 
strip( ticks[i], interval );
 
  648        for ( 
int j = 0; j < ticks[i].count(); j++ )
 
  650            if ( qwtFuzzyCompare( ticks[i][j], 0.0, stepSize ) == 0 )
 
 
  665    const QwtInterval& interval, 
double stepSize )
 const 
  667    int numTicks = qRound( interval.
width() / stepSize ) + 1;
 
  668    if ( numTicks > 10000 )
 
  672    ticks.reserve( numTicks );
 
  675    for ( 
int i = 1; i < numTicks - 1; i++ )
 
  676        ticks += interval.
minValue() + i * stepSize;
 
 
  694    int maxMinorSteps, 
double stepSize,
 
  698    double minStep = qwtStepSize( stepSize, maxMinorSteps, 
base() );
 
  699    if ( minStep == 0.0 )
 
  703    const int numTicks = qwtCeil( qAbs( stepSize / minStep ) ) - 1;
 
  707        medIndex = numTicks / 2;
 
  711    for ( 
int i = 0; i < majorTicks.count(); i++ )
 
  713        double val = majorTicks[i];
 
  714        for ( 
int k = 0; k < numTicks; k++ )
 
  718            double alignedValue = val;
 
  719            if ( qwtFuzzyCompare( val, 0.0, stepSize ) == 0 )
 
  723                mediumTicks += alignedValue;
 
  725                minorTicks += alignedValue;
 
 
  742    const QwtInterval& interval, 
double stepSize )
 const 
  750    const double eps = 0.000000000001; 
 
  751    const double max = std::numeric_limits< double >::max();
 
  753    if ( -max + stepSize <= x1 )
 
  756        if ( qAbs(x) <= eps || !qFuzzyCompare( x1, x ) )
 
  760    if ( max - stepSize >= x2 )
 
  763        if ( qAbs(x) <= eps || !qFuzzyCompare( x2, x ) )
 
 
  798    double& x1, 
double& x2, 
double& stepSize )
 const 
  803    const double logBase = 
base();
 
  817        linearScaler.
autoScale( maxNumSteps, x1, x2, stepSize );
 
  820        linearInterval = linearInterval.
limited(
 
  836        const double delta = qwtMaxF( interval.
maxValue() / logRef,
 
  838        interval.
setInterval( logRef / delta, logRef * delta );
 
  842        interval = interval.
extend( logRef );
 
  846    if ( interval.
width() == 0.0 )
 
  849    stepSize = 
divideInterval( qwtLogInterval( logBase, interval ).width(),
 
  850        qMax( maxNumSteps, 1 ) );
 
  851    if ( stepSize < 1.0 )
 
  855        interval = 
align( interval, stepSize );
 
  863        stepSize = -stepSize;
 
 
  880    int maxMajorSteps, 
int maxMinorSteps, 
double stepSize )
 const 
  885    if ( interval.
width() <= 0 )
 
  888    const double logBase = 
base();
 
  900            maxMajorSteps, maxMinorSteps, 0.0 );
 
  903    stepSize = qAbs( stepSize );
 
  904    if ( stepSize == 0.0 )
 
  906        if ( maxMajorSteps < 1 )
 
  910            qwtLogInterval( logBase, interval ).width(), maxMajorSteps );
 
  911        if ( stepSize < 1.0 )
 
  916    if ( stepSize != 0.0 )
 
  919        buildTicks( interval, stepSize, maxMinorSteps, ticks );
 
 
  941    const QwtInterval& interval, 
double stepSize, 
int maxMinorSteps,
 
  949    if ( maxMinorSteps > 0 )
 
  956        ticks[i] = 
strip( ticks[i], interval );
 
 
  968    const QwtInterval& interval, 
double stepSize )
 const 
  970    double width = qwtLogInterval( 
base(), interval ).
width();
 
  972    int numTicks = qRound( width / stepSize ) + 1;
 
  973    if ( numTicks > 10000 )
 
  976    const double lxmin = std::log( interval.
minValue() );
 
  977    const double lxmax = std::log( interval.
maxValue() );
 
  978    const double lstep = ( lxmax - lxmin ) / 
double( numTicks - 1 );
 
  981    ticks.reserve( numTicks );
 
  985    for ( 
int i = 1; i < numTicks - 1; i++ )
 
  986        ticks += std::exp( lxmin + 
double( i ) * lstep );
 
 
 1004    int maxMinorSteps, 
double stepSize,
 
 1008    const double logBase = 
base();
 
 1010    if ( stepSize < 1.1 )          
 
 1013        if ( minStep == 0.0 )
 
 1016        const int numSteps = qRound( stepSize / minStep );
 
 1018        int mediumTickIndex = -1;
 
 1019        if ( ( numSteps > 2 ) && ( numSteps % 2 == 0 ) )
 
 1020            mediumTickIndex = numSteps / 2;
 
 1022        for ( 
int i = 0; i < majorTicks.count() - 1; i++ )
 
 1024            const double v = majorTicks[i];
 
 1025            const double s = logBase / numSteps;
 
 1029                if ( !qFuzzyCompare( s, 1.0 ) )
 
 1030                    minorTicks += v * s;
 
 1032                for ( 
int j = 2; j < numSteps; j++ )
 
 1034                    minorTicks += v * j * s;
 
 1039                for ( 
int j = 1; j < numSteps; j++ )
 
 1041                    const double tick = v + j * v * ( logBase - 1 ) / numSteps;
 
 1042                    if ( j == mediumTickIndex )
 
 1043                        mediumTicks += tick;
 
 1053        if ( minStep == 0.0 )
 
 1056        if ( minStep < 1.0 )
 
 1060        int numTicks = qRound( stepSize / minStep ) - 1;
 
 1063        if ( qwtFuzzyCompare( ( numTicks + 1 ) * minStep,
 
 1064            stepSize, stepSize ) > 0 )
 
 1072        int mediumTickIndex = -1;
 
 1073        if ( ( numTicks > 2 ) && ( numTicks % 2 ) )
 
 1074            mediumTickIndex = numTicks / 2;
 
 1077        const qreal minFactor = qwtMaxF( std::pow( logBase, minStep ), logBase );
 
 1079        for ( 
int i = 0; i < majorTicks.count(); i++ )
 
 1081            double tick = majorTicks[i];
 
 1082            for ( 
int j = 0; j < numTicks; j++ )
 
 1086                if ( j == mediumTickIndex )
 
 1087                    mediumTicks += tick;
 
 
 1107    const QwtInterval& interval, 
double stepSize )
 const 
 1112    if ( qwtFuzzyCompare( interval.
minValue(), x1, stepSize ) == 0 )
 
 1116    if ( qwtFuzzyCompare( interval.
maxValue(), x2, stepSize ) == 0 )
 
 
A class representing an interval.
void setInterval(double minValue, double maxValue, BorderFlags=IncludeBorders)
QwtInterval normalized() const
Normalize the limits of the interval.
double width() const
Return the width of an interval.
long double widthL() const
Return the width of an interval as long double.
QwtInterval limited(double lowerBound, double upperBound) const
QwtInterval extend(double value) const
Extend the interval.
QwtInterval symmetrize(double value) const
A scale engine for linear scales.
void buildMinorTicks(const QList< double > &majorTicks, int maxMinorSteps, double stepSize, QList< double > &minorTicks, QList< double > &mediumTicks) const
Calculate minor/medium ticks for major ticks.
virtual void autoScale(int maxNumSteps, double &x1, double &x2, double &stepSize) const override
void buildTicks(const QwtInterval &, double stepSize, int maxMinorSteps, QList< double > ticks[QwtScaleDiv::NTickTypes]) const
Calculate ticks for an interval.
QList< double > buildMajorTicks(const QwtInterval &interval, double stepSize) const
Calculate major ticks for an interval.
QwtLinearScaleEngine(uint base=10)
virtual ~QwtLinearScaleEngine()
Destructor.
virtual QwtScaleDiv divideScale(double x1, double x2, int maxMajorSteps, int maxMinorSteps, double stepSize=0.0) const override
Calculate a scale division for an interval.
QwtInterval align(const QwtInterval &, double stepSize) const
Align an interval to a step size.
QList< double > buildMajorTicks(const QwtInterval &interval, double stepSize) const
Calculate major ticks for an interval.
void buildMinorTicks(const QList< double > &majorTicks, int maxMinorSteps, double stepSize, QList< double > &minorTicks, QList< double > &mediumTicks) const
Calculate minor/medium ticks for major ticks.
void buildTicks(const QwtInterval &, double stepSize, int maxMinorSteps, QList< double > ticks[QwtScaleDiv::NTickTypes]) const
Calculate ticks for an interval.
virtual QwtScaleDiv divideScale(double x1, double x2, int maxMajorSteps, int maxMinorSteps, double stepSize=0.0) const override
Calculate a scale division for an interval.
QwtLogScaleEngine(uint base=10)
virtual void autoScale(int maxNumSteps, double &x1, double &x2, double &stepSize) const override
QwtInterval align(const QwtInterval &, double stepSize) const
Align an interval to a step size.
virtual ~QwtLogScaleEngine()
Destructor.
static double divideEps(double intervalSize, double numSteps)
Divide an interval into steps.
static double ceilEps(double value, double intervalSize)
static double floorEps(double value, double intervalSize)
static double divideInterval(double intervalSize, int numSteps, uint base)
A class representing a scale division.
@ MediumTick
Medium ticks.
@ NTickTypes
Number of valid tick types.
Base class for scale engines.
QwtTransform * transformation() const
QFlags< Attribute > Attributes
QwtScaleEngine(uint base=10)
QList< double > strip(const QList< double > &, const QwtInterval &) const
@ Inverted
Turn the scale upside down.
@ NoAttribute
No attributes.
@ Symmetric
Build a scale which is symmetric to the reference() value.
@ IncludeReference
Build a scale which includes the reference() value.
double divideInterval(double intervalSize, int numSteps) const
double upperMargin() const
bool contains(const QwtInterval &, double value) const
bool testAttribute(Attribute) const
QwtInterval buildInterval(double value) const
Build an interval around a value.
void setReference(double)
Specify a reference point.
virtual ~QwtScaleEngine()
Destructor.
double lowerMargin() const
void setAttributes(Attributes)
void setAttribute(Attribute, bool on=true)
void setTransformation(QwtTransform *)
Attributes attributes() const
void setMargins(double lower, double upper)
Specify margins at the scale's endpoints.