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.