10 #include "qwt_scale_engine.h" 
   12 #include "qwt_interval.h" 
   13 #include "qwt_transform.h" 
   19 static 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() ) );
 
   39 static 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;
 
   63 static 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;
 
   96 static 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;
 
  186 class 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.