double QwtPlotRescaler::pixelDist( int axis, const QSize &size ) const
{
    const QwtInterval intv = intervalHint( axis );

    double dist = 0.0;
    if ( !intv.isNull() )
    {
        if ( axis == referenceAxis() )
            dist = intv.width();
        else
        {
            const double r = aspectRatio( axis );
            if ( r > 0.0 )
                dist = intv.width() * r;
        }
    }

    if ( dist > 0.0 )
    {
        if ( orientation( axis ) == Qt::Horizontal )
            dist /= size.width();
        else
            dist /= size.height();
    }

    return dist;
}
/*!
  Synchronize an axis scale according to the scale of the reference axis

  \param axis Axis index ( see QwtPlot::AxisId )
  \param reference Interval of the reference axis
  \param size Size of the canvas

  \return New interval for axis
*/
QwtInterval QwtPlotRescaler::syncScale( int axis,
    const QwtInterval& reference, const QSize &size ) const
{
    double dist;
    if ( orientation( referenceAxis() ) == Qt::Horizontal )
        dist = reference.width() / size.width();
    else
        dist = reference.width() / size.height();

    if ( orientation( axis ) == Qt::Horizontal )
        dist *= size.width();
    else
        dist *= size.height();

    dist /= aspectRatio( axis );

    QwtInterval intv;
    if ( rescalePolicy() == Fitting )
        intv = intervalHint( axis );
    else
        intv = interval( axis );

    intv = expandInterval( intv, dist, expandingDirection( axis ) );

    return intv;
}
/*!
   Update the axes scales

   \param intervals Scale intervals
*/
void QwtPlotRescaler::updateScales(
    QwtInterval intervals[QwtPlot::axisCnt] ) const
{
    if ( d_data->inReplot >= 5 )
    {
        return;
    }

    QwtPlot *plt = const_cast<QwtPlot *>( plot() );

    const bool doReplot = plt->autoReplot();
    plt->setAutoReplot( false );

    for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
    {
        if ( axis == referenceAxis() || aspectRatio( axis ) > 0.0 )
        {
            double v1 = intervals[axis].minValue();
            double v2 = intervals[axis].maxValue();

            if ( plt->axisScaleDiv( axis )->lowerBound() >
                plt->axisScaleDiv( axis )->upperBound() )
            {
                qSwap( v1, v2 );
            }

            if ( d_data->inReplot >= 1 )
            {
                d_data->axisData[axis].scaleDiv = *plt->axisScaleDiv( axis );
            }

            if ( d_data->inReplot >= 2 )
            {
                QList<double> ticks[QwtScaleDiv::NTickTypes];
                for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
                    ticks[i] = d_data->axisData[axis].scaleDiv.ticks( i );

                plt->setAxisScaleDiv( axis, QwtScaleDiv( v1, v2, ticks ) );
            }
            else
            {
                plt->setAxisScale( axis, v1, v2 );
            }
        }
    }

    const bool immediatePaint = 
        plt->canvas()->testPaintAttribute( QwtPlotCanvas::ImmediatePaint );
    plt->canvas()->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, false );

    plt->setAutoReplot( doReplot );

    d_data->inReplot++;
    plt->replot();
    d_data->inReplot--;

    plt->canvas()->setPaintAttribute( 
        QwtPlotCanvas::ImmediatePaint, immediatePaint );
}
/*!
   Update the axes scales 

   \param intervals Scale intervals
*/
void QwtPlotRescaler::updateScales(
    QwtDoubleInterval intervals[QwtPlot::axisCnt]) const
{
    if ( d_data->inReplot >= 5 )
    {
        return;
    }

    QwtPlot *plt = (QwtPlot *)plot();

    const bool doReplot = plt->autoReplot();
    plt->setAutoReplot(false);

    for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
    {
        if ( axis == referenceAxis() || aspectRatio(axis) > 0.0 )
        {
            double v1 = intervals[axis].minValue();
            double v2 = intervals[axis].maxValue();

            if ( plt->axisScaleDiv(axis)->lowerBound() >
                plt->axisScaleDiv(axis)->upperBound() )
            {
                qSwap(v1, v2);
            }

            if ( d_data->inReplot >= 1 )
            {
                d_data->axisData[axis].scaleDiv = *plt->axisScaleDiv(axis);
            }

            if ( d_data->inReplot >= 2 )
            {
                QwtValueList ticks[QwtScaleDiv::NTickTypes];
                for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
                    ticks[i] = d_data->axisData[axis].scaleDiv.ticks(i);

                plt->setAxisScaleDiv(axis, QwtScaleDiv(v1, v2, ticks));
            }
            else
            {
                plt->setAxisScale(axis, v1, v2);
            }
        }
    }

    plt->setAutoReplot(doReplot);

    d_data->inReplot++;
    plt->replot();
    d_data->inReplot--;
}
/*!
   Adjust the plot axes scales

   \param oldSize Previous size of the canvas
   \param newSize New size of the canvas
*/
void QwtPlotRescaler::rescale(
    const QSize &oldSize, const QSize &newSize ) const
{
    if ( newSize.isEmpty() )
        return;

    QwtInterval intervals[QwtPlot::axisCnt];
    for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
        intervals[axis] = interval( axis );

    const int refAxis = referenceAxis();
    intervals[refAxis] = expandScale( refAxis, oldSize, newSize );

    for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
    {
        if ( aspectRatio( axis ) > 0.0 && axis != refAxis )
            intervals[axis] = syncScale( axis, intervals[refAxis], newSize );
    }

    updateScales( intervals );
}
//! Adjust the plot axes scales
void QwtPlotRescaler::rescale() const
{
#if 0
    const int axis = referenceAxis();
    if ( axis < 0 || axis >= QwtPlot::axisCnt )
        return;

    const QwtDoubleInterval hint = intervalHint(axis);
    if ( !hint.isNull() )
    {
        QwtPlot *plt = (QwtPlot *)plot();

        const bool doReplot = plt->autoReplot();
        plt->setAutoReplot(false);
        plt->setAxisScale(axis, hint.minValue(), hint.maxValue());
        plt->setAutoReplot(doReplot);
        plt->updateAxes();
    }
#endif

    const QSize size = canvas()->contentsRect().size();
    rescale(size, size);
}