00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_scale_engine.h"
00011 #include "qwt_math.h"
00012 #include "qwt_scale_map.h"
00013 #include <qalgorithms.h>
00014 #include <qmath.h>
00015 #include <float.h>
00016 #include <limits>
00017
00018 #if QT_VERSION < 0x040601
00019 #define qFabs(x) ::fabs(x)
00020 #define qExp(x) ::exp(x)
00021 #endif
00022
00023 static inline double qwtLog( double base, double value )
00024 {
00025 return log( value ) / log( base );
00026 }
00027
00028 static inline QwtInterval qwtLogInterval( double base, const QwtInterval &interval )
00029 {
00030 return QwtInterval( qwtLog( base, interval.minValue() ),
00031 qwtLog( base, interval.maxValue() ) );
00032 }
00033
00034 static inline QwtInterval qwtPowInterval( double base, const QwtInterval &interval )
00035 {
00036 return QwtInterval( qPow( base, interval.minValue() ),
00037 qPow( base, interval.maxValue() ) );
00038 }
00039
00040
00041 #if 1
00042
00043
00044 static double qwtStepSize( double intervalSize, int maxSteps, uint base )
00045 {
00046 const double minStep =
00047 QwtScaleArithmetic::divideInterval( intervalSize, maxSteps, base );
00048
00049 if ( minStep != 0.0 )
00050 {
00051
00052 const int numTicks = qCeil( qAbs( intervalSize / minStep ) ) - 1;
00053
00054
00055 if ( qwtFuzzyCompare( ( numTicks + 1 ) * qAbs( minStep ),
00056 qAbs( intervalSize ), intervalSize ) > 0 )
00057 {
00058
00059 return 0.5 * intervalSize;
00060 }
00061 }
00062
00063 return minStep;
00064 }
00065
00066 #else
00067
00068 static double qwtStepSize( double intervalSize, int maxSteps, uint base )
00069 {
00070 if ( maxSteps <= 0 )
00071 return 0.0;
00072
00073 if ( maxSteps > 2 )
00074 {
00075 for ( int numSteps = maxSteps; numSteps > 1; numSteps-- )
00076 {
00077 const double stepSize = intervalSize / numSteps;
00078
00079 const double p = ::floor( ::log( stepSize ) / ::log( base ) );
00080 const double fraction = qPow( base, p );
00081
00082 for ( uint n = base; n > 1; n /= 2 )
00083 {
00084 if ( qFuzzyCompare( stepSize, n * fraction ) )
00085 return stepSize;
00086
00087 if ( n == 3 && ( base % 2 ) == 0 )
00088 {
00089 if ( qFuzzyCompare( stepSize, 2 * fraction ) )
00090 return stepSize;
00091 }
00092 }
00093 }
00094 }
00095
00096 return intervalSize * 0.5;
00097 }
00098
00099 #endif
00100
00101 static const double _eps = 1.0e-6;
00102
00113 double QwtScaleArithmetic::ceilEps( double value,
00114 double intervalSize )
00115 {
00116 const double eps = _eps * intervalSize;
00117
00118 value = ( value - eps ) / intervalSize;
00119 return ::ceil( value ) * intervalSize;
00120 }
00121
00131 double QwtScaleArithmetic::floorEps( double value, double intervalSize )
00132 {
00133 const double eps = _eps * intervalSize;
00134
00135 value = ( value + eps ) / intervalSize;
00136 return ::floor( value ) * intervalSize;
00137 }
00138
00148 double QwtScaleArithmetic::divideEps( double intervalSize, double numSteps )
00149 {
00150 if ( numSteps == 0.0 || intervalSize == 0.0 )
00151 return 0.0;
00152
00153 return ( intervalSize - ( _eps * intervalSize ) ) / numSteps;
00154 }
00155
00165 double QwtScaleArithmetic::divideInterval(
00166 double intervalSize, int numSteps, uint base )
00167 {
00168 if ( numSteps <= 0 )
00169 return 0.0;
00170
00171 const double v = QwtScaleArithmetic::divideEps( intervalSize, numSteps );
00172 if ( v == 0.0 )
00173 return 0.0;
00174
00175 const double lx = qwtLog( base, qFabs( v ) );
00176 const double p = ::floor( lx );
00177
00178 const double fraction = qPow( base, lx - p );
00179
00180 uint n = base;
00181 while ( ( n > 1 ) && ( fraction <= n / 2 ) )
00182 n /= 2;
00183
00184 double stepSize = n * qPow( base, p );
00185 if ( v < 0 )
00186 stepSize = -stepSize;
00187
00188 return stepSize;
00189 }
00190
00191 class QwtScaleEngine::PrivateData
00192 {
00193 public:
00194 PrivateData():
00195 attributes( QwtScaleEngine::NoAttribute ),
00196 lowerMargin( 0.0 ),
00197 upperMargin( 0.0 ),
00198 referenceValue( 0.0 ),
00199 base( 10 ),
00200 transform( NULL )
00201 {
00202 }
00203
00204 ~PrivateData()
00205 {
00206 delete transform;
00207 }
00208
00209 QwtScaleEngine::Attributes attributes;
00210
00211 double lowerMargin;
00212 double upperMargin;
00213
00214 double referenceValue;
00215
00216 uint base;
00217
00218 QwtTransform* transform;
00219 };
00220
00227 QwtScaleEngine::QwtScaleEngine( uint base )
00228 {
00229 d_data = new PrivateData;
00230 setBase( base );
00231 }
00232
00233
00235 QwtScaleEngine::~QwtScaleEngine ()
00236 {
00237 delete d_data;
00238 }
00239
00253 void QwtScaleEngine::setTransformation( QwtTransform *transform )
00254 {
00255 if ( transform != d_data->transform )
00256 {
00257 delete d_data->transform;
00258 d_data->transform = transform;
00259 }
00260 }
00261
00270 QwtTransform *QwtScaleEngine::transformation() const
00271 {
00272 QwtTransform *transform = NULL;
00273 if ( d_data->transform )
00274 transform = d_data->transform->copy();
00275
00276 return transform;
00277 }
00278
00285 double QwtScaleEngine::lowerMargin() const
00286 {
00287 return d_data->lowerMargin;
00288 }
00289
00296 double QwtScaleEngine::upperMargin() const
00297 {
00298 return d_data->upperMargin;
00299 }
00300
00317 void QwtScaleEngine::setMargins( double lower, double upper )
00318 {
00319 d_data->lowerMargin = qMax( lower, 0.0 );
00320 d_data->upperMargin = qMax( upper, 0.0 );
00321 }
00322
00331 double QwtScaleEngine::divideInterval(
00332 double intervalSize, int numSteps ) const
00333 {
00334 return QwtScaleArithmetic::divideInterval(
00335 intervalSize, numSteps, d_data->base );
00336 }
00337
00346 bool QwtScaleEngine::contains(
00347 const QwtInterval &interval, double value ) const
00348 {
00349 if ( !interval.isValid() )
00350 return false;
00351
00352 if ( qwtFuzzyCompare( value, interval.minValue(), interval.width() ) < 0 )
00353 return false;
00354
00355 if ( qwtFuzzyCompare( value, interval.maxValue(), interval.width() ) > 0 )
00356 return false;
00357
00358 return true;
00359 }
00360
00369 QList<double> QwtScaleEngine::strip( const QList<double>& ticks,
00370 const QwtInterval &interval ) const
00371 {
00372 if ( !interval.isValid() || ticks.count() == 0 )
00373 return QList<double>();
00374
00375 if ( contains( interval, ticks.first() )
00376 && contains( interval, ticks.last() ) )
00377 {
00378 return ticks;
00379 }
00380
00381 QList<double> strippedTicks;
00382 for ( int i = 0; i < ticks.count(); i++ )
00383 {
00384 if ( contains( interval, ticks[i] ) )
00385 strippedTicks += ticks[i];
00386 }
00387 return strippedTicks;
00388 }
00389
00400 QwtInterval QwtScaleEngine::buildInterval( double value ) const
00401 {
00402 const double delta = ( value == 0.0 ) ? 0.5 : qAbs( 0.5 * value );
00403
00404 if ( DBL_MAX - delta < value )
00405 return QwtInterval( DBL_MAX - delta, DBL_MAX );
00406
00407 if ( -DBL_MAX + delta > value )
00408 return QwtInterval( -DBL_MAX, -DBL_MAX + delta );
00409
00410 return QwtInterval( value - delta, value + delta );
00411 }
00412
00421 void QwtScaleEngine::setAttribute( Attribute attribute, bool on )
00422 {
00423 if ( on )
00424 d_data->attributes |= attribute;
00425 else
00426 d_data->attributes &= ~attribute;
00427 }
00428
00435 bool QwtScaleEngine::testAttribute( Attribute attribute ) const
00436 {
00437 return ( d_data->attributes & attribute );
00438 }
00439
00446 void QwtScaleEngine::setAttributes( Attributes attributes )
00447 {
00448 d_data->attributes = attributes;
00449 }
00450
00455 QwtScaleEngine::Attributes QwtScaleEngine::attributes() const
00456 {
00457 return d_data->attributes;
00458 }
00459
00469 void QwtScaleEngine::setReference( double r )
00470 {
00471 d_data->referenceValue = r;
00472 }
00473
00478 double QwtScaleEngine::reference() const
00479 {
00480 return d_data->referenceValue;
00481 }
00482
00495 void QwtScaleEngine::setBase( uint base )
00496 {
00497 d_data->base = qMax( base, 2U );
00498 }
00499
00504 uint QwtScaleEngine::base() const
00505 {
00506 return d_data->base;
00507 }
00508
00515 QwtLinearScaleEngine::QwtLinearScaleEngine( uint base ):
00516 QwtScaleEngine( base )
00517 {
00518 }
00519
00521 QwtLinearScaleEngine::~QwtLinearScaleEngine()
00522 {
00523 }
00524
00535 void QwtLinearScaleEngine::autoScale( int maxNumSteps,
00536 double &x1, double &x2, double &stepSize ) const
00537 {
00538 QwtInterval interval( x1, x2 );
00539 interval = interval.normalized();
00540
00541 interval.setMinValue( interval.minValue() - lowerMargin() );
00542 interval.setMaxValue( interval.maxValue() + upperMargin() );
00543
00544 if ( testAttribute( QwtScaleEngine::Symmetric ) )
00545 interval = interval.symmetrize( reference() );
00546
00547 if ( testAttribute( QwtScaleEngine::IncludeReference ) )
00548 interval = interval.extend( reference() );
00549
00550 if ( interval.width() == 0.0 )
00551 interval = buildInterval( interval.minValue() );
00552
00553 stepSize = QwtScaleArithmetic::divideInterval(
00554 interval.width(), qMax( maxNumSteps, 1 ), base() );
00555
00556 if ( !testAttribute( QwtScaleEngine::Floating ) )
00557 interval = align( interval, stepSize );
00558
00559 x1 = interval.minValue();
00560 x2 = interval.maxValue();
00561
00562 if ( testAttribute( QwtScaleEngine::Inverted ) )
00563 {
00564 qSwap( x1, x2 );
00565 stepSize = -stepSize;
00566 }
00567 }
00568
00581 QwtScaleDiv QwtLinearScaleEngine::divideScale( double x1, double x2,
00582 int maxMajorSteps, int maxMinorSteps, double stepSize ) const
00583 {
00584 QwtInterval interval = QwtInterval( x1, x2 ).normalized();
00585
00586 if ( interval.widthL() > std::numeric_limits<double>::max() )
00587 {
00588 qWarning() << "QwtLinearScaleEngine::divideScale: overflow";
00589 return QwtScaleDiv();
00590 }
00591
00592 if ( interval.width() <= 0 )
00593 return QwtScaleDiv();
00594
00595 stepSize = qAbs( stepSize );
00596 if ( stepSize == 0.0 )
00597 {
00598 if ( maxMajorSteps < 1 )
00599 maxMajorSteps = 1;
00600
00601 stepSize = QwtScaleArithmetic::divideInterval(
00602 interval.width(), maxMajorSteps, base() );
00603 }
00604
00605 QwtScaleDiv scaleDiv;
00606
00607 if ( stepSize != 0.0 )
00608 {
00609 QList<double> ticks[QwtScaleDiv::NTickTypes];
00610 buildTicks( interval, stepSize, maxMinorSteps, ticks );
00611
00612 scaleDiv = QwtScaleDiv( interval, ticks );
00613 }
00614
00615 if ( x1 > x2 )
00616 scaleDiv.invert();
00617
00618 return scaleDiv;
00619 }
00620
00631 void QwtLinearScaleEngine::buildTicks(
00632 const QwtInterval& interval, double stepSize, int maxMinorSteps,
00633 QList<double> ticks[QwtScaleDiv::NTickTypes] ) const
00634 {
00635 const QwtInterval boundingInterval = align( interval, stepSize );
00636
00637 ticks[QwtScaleDiv::MajorTick] =
00638 buildMajorTicks( boundingInterval, stepSize );
00639
00640 if ( maxMinorSteps > 0 )
00641 {
00642 buildMinorTicks( ticks[QwtScaleDiv::MajorTick], maxMinorSteps, stepSize,
00643 ticks[QwtScaleDiv::MinorTick], ticks[QwtScaleDiv::MediumTick] );
00644 }
00645
00646 for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
00647 {
00648 ticks[i] = strip( ticks[i], interval );
00649
00650
00651
00652
00653 for ( int j = 0; j < ticks[i].count(); j++ )
00654 {
00655 if ( qwtFuzzyCompare( ticks[i][j], 0.0, stepSize ) == 0 )
00656 ticks[i][j] = 0.0;
00657 }
00658 }
00659 }
00660
00669 QList<double> QwtLinearScaleEngine::buildMajorTicks(
00670 const QwtInterval &interval, double stepSize ) const
00671 {
00672 int numTicks = qRound( interval.width() / stepSize ) + 1;
00673 if ( numTicks > 10000 )
00674 numTicks = 10000;
00675
00676 QList<double> ticks;
00677
00678 ticks += interval.minValue();
00679 for ( int i = 1; i < numTicks - 1; i++ )
00680 ticks += interval.minValue() + i * stepSize;
00681 ticks += interval.maxValue();
00682
00683 return ticks;
00684 }
00685
00696 void QwtLinearScaleEngine::buildMinorTicks(
00697 const QList<double>& majorTicks,
00698 int maxMinorSteps, double stepSize,
00699 QList<double> &minorTicks,
00700 QList<double> &mediumTicks ) const
00701 {
00702 double minStep = qwtStepSize( stepSize, maxMinorSteps, base() );
00703 if ( minStep == 0.0 )
00704 return;
00705
00706
00707 const int numTicks = qCeil( qAbs( stepSize / minStep ) ) - 1;
00708
00709 int medIndex = -1;
00710 if ( numTicks % 2 )
00711 medIndex = numTicks / 2;
00712
00713
00714
00715 for ( int i = 0; i < majorTicks.count(); i++ )
00716 {
00717 double val = majorTicks[i];
00718 for ( int k = 0; k < numTicks; k++ )
00719 {
00720 val += minStep;
00721
00722 double alignedValue = val;
00723 if ( qwtFuzzyCompare( val, 0.0, stepSize ) == 0 )
00724 alignedValue = 0.0;
00725
00726 if ( k == medIndex )
00727 mediumTicks += alignedValue;
00728 else
00729 minorTicks += alignedValue;
00730 }
00731 }
00732 }
00733
00745 QwtInterval QwtLinearScaleEngine::align(
00746 const QwtInterval &interval, double stepSize ) const
00747 {
00748 double x1 = interval.minValue();
00749 double x2 = interval.maxValue();
00750
00751
00752
00753
00754 const double eps = 0.000000000001;
00755 if ( -DBL_MAX + stepSize <= x1 )
00756 {
00757 const double x = QwtScaleArithmetic::floorEps( x1, stepSize );
00758 if ( qAbs(x) <= eps || !qFuzzyCompare( x1, x ) )
00759 x1 = x;
00760 }
00761
00762 if ( DBL_MAX - stepSize >= x2 )
00763 {
00764 const double x = QwtScaleArithmetic::ceilEps( x2, stepSize );
00765 if ( qAbs(x) <= eps || !qFuzzyCompare( x2, x ) )
00766 x2 = x;
00767 }
00768
00769 return QwtInterval( x1, x2 );
00770 }
00771
00778 QwtLogScaleEngine::QwtLogScaleEngine( uint base ):
00779 QwtScaleEngine( base )
00780 {
00781 setTransformation( new QwtLogTransform() );
00782 }
00783
00785 QwtLogScaleEngine::~QwtLogScaleEngine()
00786 {
00787 }
00788
00799 void QwtLogScaleEngine::autoScale( int maxNumSteps,
00800 double &x1, double &x2, double &stepSize ) const
00801 {
00802 if ( x1 > x2 )
00803 qSwap( x1, x2 );
00804
00805 const double logBase = base();
00806
00807 QwtInterval interval( x1 / qPow( logBase, lowerMargin() ),
00808 x2 * qPow( logBase, upperMargin() ) );
00809
00810 if ( interval.maxValue() / interval.minValue() < logBase )
00811 {
00812
00813
00814 QwtLinearScaleEngine linearScaler;
00815 linearScaler.setAttributes( attributes() );
00816 linearScaler.setReference( reference() );
00817 linearScaler.setMargins( lowerMargin(), upperMargin() );
00818
00819 linearScaler.autoScale( maxNumSteps, x1, x2, stepSize );
00820
00821 QwtInterval linearInterval = QwtInterval( x1, x2 ).normalized();
00822 linearInterval = linearInterval.limited( LOG_MIN, LOG_MAX );
00823
00824 if ( linearInterval.maxValue() / linearInterval.minValue() < logBase )
00825 {
00826 stepSize = 0.0;
00827 return;
00828 }
00829 }
00830
00831 double logRef = 1.0;
00832 if ( reference() > LOG_MIN / 2 )
00833 logRef = qMin( reference(), LOG_MAX / 2 );
00834
00835 if ( testAttribute( QwtScaleEngine::Symmetric ) )
00836 {
00837 const double delta = qMax( interval.maxValue() / logRef,
00838 logRef / interval.minValue() );
00839 interval.setInterval( logRef / delta, logRef * delta );
00840 }
00841
00842 if ( testAttribute( QwtScaleEngine::IncludeReference ) )
00843 interval = interval.extend( logRef );
00844
00845 interval = interval.limited( LOG_MIN, LOG_MAX );
00846
00847 if ( interval.width() == 0.0 )
00848 interval = buildInterval( interval.minValue() );
00849
00850 stepSize = divideInterval( qwtLogInterval( logBase, interval ).width(),
00851 qMax( maxNumSteps, 1 ) );
00852 if ( stepSize < 1.0 )
00853 stepSize = 1.0;
00854
00855 if ( !testAttribute( QwtScaleEngine::Floating ) )
00856 interval = align( interval, stepSize );
00857
00858 x1 = interval.minValue();
00859 x2 = interval.maxValue();
00860
00861 if ( testAttribute( QwtScaleEngine::Inverted ) )
00862 {
00863 qSwap( x1, x2 );
00864 stepSize = -stepSize;
00865 }
00866 }
00867
00880 QwtScaleDiv QwtLogScaleEngine::divideScale( double x1, double x2,
00881 int maxMajorSteps, int maxMinorSteps, double stepSize ) const
00882 {
00883 QwtInterval interval = QwtInterval( x1, x2 ).normalized();
00884 interval = interval.limited( LOG_MIN, LOG_MAX );
00885
00886 if ( interval.width() <= 0 )
00887 return QwtScaleDiv();
00888
00889 const double logBase = base();
00890
00891 if ( interval.maxValue() / interval.minValue() < logBase )
00892 {
00893
00894
00895 QwtLinearScaleEngine linearScaler;
00896 linearScaler.setAttributes( attributes() );
00897 linearScaler.setReference( reference() );
00898 linearScaler.setMargins( lowerMargin(), upperMargin() );
00899
00900 return linearScaler.divideScale( x1, x2,
00901 maxMajorSteps, maxMinorSteps, 0.0 );
00902 }
00903
00904 stepSize = qAbs( stepSize );
00905 if ( stepSize == 0.0 )
00906 {
00907 if ( maxMajorSteps < 1 )
00908 maxMajorSteps = 1;
00909
00910 stepSize = divideInterval(
00911 qwtLogInterval( logBase, interval ).width(), maxMajorSteps );
00912 if ( stepSize < 1.0 )
00913 stepSize = 1.0;
00914 }
00915
00916 QwtScaleDiv scaleDiv;
00917 if ( stepSize != 0.0 )
00918 {
00919 QList<double> ticks[QwtScaleDiv::NTickTypes];
00920 buildTicks( interval, stepSize, maxMinorSteps, ticks );
00921
00922 scaleDiv = QwtScaleDiv( interval, ticks );
00923 }
00924
00925 if ( x1 > x2 )
00926 scaleDiv.invert();
00927
00928 return scaleDiv;
00929 }
00930
00941 void QwtLogScaleEngine::buildTicks(
00942 const QwtInterval& interval, double stepSize, int maxMinorSteps,
00943 QList<double> ticks[QwtScaleDiv::NTickTypes] ) const
00944 {
00945 const QwtInterval boundingInterval = align( interval, stepSize );
00946
00947 ticks[QwtScaleDiv::MajorTick] =
00948 buildMajorTicks( boundingInterval, stepSize );
00949
00950 if ( maxMinorSteps > 0 )
00951 {
00952 buildMinorTicks( ticks[QwtScaleDiv::MajorTick], maxMinorSteps, stepSize,
00953 ticks[QwtScaleDiv::MinorTick], ticks[QwtScaleDiv::MediumTick] );
00954 }
00955
00956 for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
00957 ticks[i] = strip( ticks[i], interval );
00958 }
00959
00968 QList<double> QwtLogScaleEngine::buildMajorTicks(
00969 const QwtInterval &interval, double stepSize ) const
00970 {
00971 double width = qwtLogInterval( base(), interval ).width();
00972
00973 int numTicks = qRound( width / stepSize ) + 1;
00974 if ( numTicks > 10000 )
00975 numTicks = 10000;
00976
00977 const double lxmin = ::log( interval.minValue() );
00978 const double lxmax = ::log( interval.maxValue() );
00979 const double lstep = ( lxmax - lxmin ) / double( numTicks - 1 );
00980
00981 QList<double> ticks;
00982
00983 ticks += interval.minValue();
00984
00985 for ( int i = 1; i < numTicks - 1; i++ )
00986 ticks += qExp( lxmin + double( i ) * lstep );
00987
00988 ticks += interval.maxValue();
00989
00990 return ticks;
00991 }
00992
01002 void QwtLogScaleEngine::buildMinorTicks(
01003 const QList<double> &majorTicks,
01004 int maxMinorSteps, double stepSize,
01005 QList<double> &minorTicks,
01006 QList<double> &mediumTicks ) const
01007 {
01008 const double logBase = base();
01009
01010 if ( stepSize < 1.1 )
01011 {
01012 double minStep = divideInterval( stepSize, maxMinorSteps + 1 );
01013 if ( minStep == 0.0 )
01014 return;
01015
01016 const int numSteps = qRound( stepSize / minStep );
01017
01018 int mediumTickIndex = -1;
01019 if ( ( numSteps > 2 ) && ( numSteps % 2 == 0 ) )
01020 mediumTickIndex = numSteps / 2;
01021
01022 for ( int i = 0; i < majorTicks.count() - 1; i++ )
01023 {
01024 const double v = majorTicks[i];
01025 const double s = logBase / numSteps;
01026
01027 if ( s >= 1.0 )
01028 {
01029 if ( !qFuzzyCompare( s, 1.0 ) )
01030 minorTicks += v * s;
01031
01032 for ( int j = 2; j < numSteps; j++ )
01033 {
01034 minorTicks += v * j * s;
01035 }
01036 }
01037 else
01038 {
01039 for ( int j = 1; j < numSteps; j++ )
01040 {
01041 const double tick = v + j * v * ( logBase - 1 ) / numSteps;
01042 if ( j == mediumTickIndex )
01043 mediumTicks += tick;
01044 else
01045 minorTicks += tick;
01046 }
01047 }
01048 }
01049 }
01050 else
01051 {
01052 double minStep = divideInterval( stepSize, maxMinorSteps );
01053 if ( minStep == 0.0 )
01054 return;
01055
01056 if ( minStep < 1.0 )
01057 minStep = 1.0;
01058
01059
01060 int numTicks = qRound( stepSize / minStep ) - 1;
01061
01062
01063 if ( qwtFuzzyCompare( ( numTicks + 1 ) * minStep,
01064 stepSize, stepSize ) > 0 )
01065 {
01066 numTicks = 0;
01067 }
01068
01069 if ( numTicks < 1 )
01070 return;
01071
01072 int mediumTickIndex = -1;
01073 if ( ( numTicks > 2 ) && ( numTicks % 2 ) )
01074 mediumTickIndex = numTicks / 2;
01075
01076
01077 const qreal minFactor = qMax( qPow( logBase, minStep ), qreal( logBase ) );
01078
01079 for ( int i = 0; i < majorTicks.count(); i++ )
01080 {
01081 double tick = majorTicks[i];
01082 for ( int j = 0; j < numTicks; j++ )
01083 {
01084 tick *= minFactor;
01085
01086 if ( j == mediumTickIndex )
01087 mediumTicks += tick;
01088 else
01089 minorTicks += tick;
01090 }
01091 }
01092 }
01093 }
01094
01106 QwtInterval QwtLogScaleEngine::align(
01107 const QwtInterval &interval, double stepSize ) const
01108 {
01109 const QwtInterval intv = qwtLogInterval( base(), interval );
01110
01111 double x1 = QwtScaleArithmetic::floorEps( intv.minValue(), stepSize );
01112 if ( qwtFuzzyCompare( interval.minValue(), x1, stepSize ) == 0 )
01113 x1 = interval.minValue();
01114
01115 double x2 = QwtScaleArithmetic::ceilEps( intv.maxValue(), stepSize );
01116 if ( qwtFuzzyCompare( interval.maxValue(), x2, stepSize ) == 0 )
01117 x2 = interval.maxValue();
01118
01119 return qwtPowInterval( base(), QwtInterval( x1, x2 ) );
01120 }