/*! Check if an interval "contains" a value \param interval Interval \param value Value \return True, when the value is inside the interval */ bool QwtScaleEngine::contains( const QwtInterval &interval, double value ) const { if ( !interval.isValid() ) return false; if ( qwtFuzzyCompare( value, interval.minValue(), interval.width() ) < 0 ) return false; if ( qwtFuzzyCompare( value, interval.maxValue(), interval.width() ) > 0 ) return false; return true; }

/*! \brief Align an interval to a step size The limits of an interval are aligned that both are integer multiples of the step size. \param interval Interval \param stepSize Step size \return Aligned interval */ QwtInterval QwtLogScaleEngine::align( const QwtInterval &interval, double stepSize ) const { const QwtInterval intv = qwtLogInterval( base(), interval ); double x1 = QwtScaleArithmetic::floorEps( intv.minValue(), stepSize ); if ( qwtFuzzyCompare( interval.minValue(), x1, stepSize ) == 0 ) x1 = interval.minValue(); double x2 = QwtScaleArithmetic::ceilEps( intv.maxValue(), stepSize ); if ( qwtFuzzyCompare( interval.maxValue(), x2, stepSize ) == 0 ) x2 = interval.maxValue(); return qwtPowInterval( base(), QwtInterval( x1, x2 ) ); }

/*! \brief Calculate ticks for an interval \param interval Interval \param stepSize Step size \param maxMinorSteps Maximum number of minor steps \param ticks Arrays to be filled with the calculated ticks \sa buildMajorTicks(), buildMinorTicks */ void QwtLinearScaleEngine::buildTicks( const QwtInterval& interval, double stepSize, int maxMinorSteps, QList<double> ticks[QwtScaleDiv::NTickTypes] ) const { const QwtInterval boundingInterval = align( interval, stepSize ); ticks[QwtScaleDiv::MajorTick] = buildMajorTicks( boundingInterval, stepSize ); if ( maxMinorSteps > 0 ) { buildMinorTicks( ticks[QwtScaleDiv::MajorTick], maxMinorSteps, stepSize, ticks[QwtScaleDiv::MinorTick], ticks[QwtScaleDiv::MediumTick] ); } for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ ) { ticks[i] = strip( ticks[i], interval ); // ticks very close to 0.0 are // explicitely set to 0.0 for ( int j = 0; j < ticks[i].count(); j++ ) { if ( qwtFuzzyCompare( ticks[i][j], 0.0, stepSize ) == 0 ) ticks[i][j] = 0.0; } } }

/*! \brief Align an interval to a step size The limits of an interval are aligned that both are integer multiples of the step size. \param interval Interval \param stepSize Step size \return Aligned interval */ QwtInterval QwtLinearScaleEngine::align( const QwtInterval &interval, double stepSize ) const { double x1 = interval.minValue(); double x2 = interval.maxValue(); if ( -DBL_MAX + stepSize <= x1 ) { const double x = QwtScaleArithmetic::floorEps( x1, stepSize ); if ( qwtFuzzyCompare( x1, x, stepSize ) != 0 ) x1 = x; } if ( DBL_MAX - stepSize >= x2 ) { const double x = QwtScaleArithmetic::ceilEps( x2, stepSize ); if ( qwtFuzzyCompare( x2, x, stepSize ) != 0 ) x2 = x; } return QwtInterval( x1, x2 ); }

/*! Transform a rectangle from scale to paint coordinates \param xMap X map \param yMap Y map \param rect Rectangle in scale coordinates \return Rectangle in paint coordinates \sa invTransform() */ QRectF QwtScaleMap::transform( const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &rect ) { double x1 = xMap.transform( rect.left() ); double x2 = xMap.transform( rect.right() ); double y1 = yMap.transform( rect.top() ); double y2 = yMap.transform( rect.bottom() ); if ( x2 < x1 ) qSwap( x1, x2 ); if ( y2 < y1 ) qSwap( y1, y2 ); if ( qwtFuzzyCompare( x1, 0.0, x2 - x1 ) == 0 ) x1 = 0.0; if ( qwtFuzzyCompare( x2, 0.0, x2 - x1 ) == 0 ) x2 = 0.0; if ( qwtFuzzyCompare( y1, 0.0, y2 - y1 ) == 0 ) y1 = 0.0; if ( qwtFuzzyCompare( y2, 0.0, y2 - y1 ) == 0 ) y2 = 0.0; return QRectF( x1, y1, x2 - x1 + 1, y2 - y1 + 1 ); }

// this version often doesn't find the best ticks: f.e for 15: 5, 10 static double qwtStepSize( double intervalSize, int maxSteps, uint base ) { const double minStep = QwtScaleArithmetic::divideInterval( intervalSize, maxSteps, base ); if ( minStep != 0.0 ) { // # ticks per interval const int numTicks = qCeil( qAbs( intervalSize / minStep ) ) - 1; // Do the minor steps fit into the interval? if ( qwtFuzzyCompare( ( numTicks + 1 ) * qAbs( minStep ), qAbs( intervalSize ), intervalSize ) > 0 ) { // The minor steps doesn't fit into the interval return 0.5 * intervalSize; } } return minStep; }

/*! \brief Calculate minor/medium ticks for major ticks \param majorTicks Major ticks \param maxMinorSteps Maximum number of minor steps \param stepSize Step size \param minorTicks Array to be filled with the calculated minor ticks \param mediumTicks Array to be filled with the calculated medium ticks */ void QwtLinearScaleEngine::buildMinorTicks( const QList<double>& majorTicks, int maxMinorSteps, double stepSize, QList<double> &minorTicks, QList<double> &mediumTicks ) const { double minStep = qwtStepSize( stepSize, maxMinorSteps, base() ); if ( minStep == 0.0 ) return; // # ticks per interval const int numTicks = qCeil( qAbs( stepSize / minStep ) ) - 1; int medIndex = -1; if ( numTicks % 2 ) medIndex = numTicks / 2; // calculate minor ticks for ( int i = 0; i < majorTicks.count(); i++ ) { double val = majorTicks[i]; for ( int k = 0; k < numTicks; k++ ) { val += minStep; double alignedValue = val; if ( qwtFuzzyCompare( val, 0.0, stepSize ) == 0 ) alignedValue = 0.0; if ( k == medIndex ) mediumTicks += alignedValue; else minorTicks += alignedValue; } } }

/*! \brief Calculate minor/medium ticks for major ticks \param majorTicks Major ticks \param maxMinorSteps Maximum number of minor steps \param stepSize Step size \param minorTicks Array to be filled with the calculated minor ticks \param mediumTicks Array to be filled with the calculated medium ticks */ void QwtLogScaleEngine::buildMinorTicks( const QList<double> &majorTicks, int maxMinorSteps, double stepSize, QList<double> &minorTicks, QList<double> &mediumTicks ) const { const double logBase = base(); if ( stepSize < 1.1 ) // major step width is one base { double minStep = divideInterval( stepSize, maxMinorSteps + 1 ); if ( minStep == 0.0 ) return; const int numSteps = qRound( stepSize / minStep ); int mediumTickIndex = -1; if ( ( numSteps > 2 ) && ( numSteps % 2 == 0 ) ) mediumTickIndex = numSteps / 2; for ( int i = 0; i < majorTicks.count() - 1; i++ ) { const double v = majorTicks[i]; const double s = logBase / numSteps; if ( s >= 1.0 ) { if ( !qFuzzyCompare( s, 1.0 ) ) minorTicks += v * s; for ( int j = 2; j < numSteps; j++ ) { minorTicks += v * j * s; } } else { for ( int j = 1; j < numSteps; j++ ) { const double tick = v + j * v * ( logBase - 1 ) / numSteps; if ( j == mediumTickIndex ) mediumTicks += tick; else minorTicks += tick; } } } } else { double minStep = divideInterval( stepSize, maxMinorSteps ); if ( minStep == 0.0 ) return; if ( minStep < 1.0 ) minStep = 1.0; // # subticks per interval int numTicks = qRound( stepSize / minStep ) - 1; // Do the minor steps fit into the interval? if ( qwtFuzzyCompare( ( numTicks + 1 ) * minStep, stepSize, stepSize ) > 0 ) { numTicks = 0; } if ( numTicks < 1 ) return; int mediumTickIndex = -1; if ( ( numTicks > 2 ) && ( numTicks % 2 ) ) mediumTickIndex = numTicks / 2; // substep factor = base^substeps const qreal minFactor = qMax( qPow( logBase, minStep ), qreal( logBase ) ); for ( int i = 0; i < majorTicks.count(); i++ ) { double tick = majorTicks[i]; for ( int j = 0; j < numTicks; j++ ) { tick *= minFactor; if ( j == mediumTickIndex ) mediumTicks += tick; else minorTicks += tick; } } } }