/*!
   \brief Return the raster to be used by the CONREC contour algorithm.

   A larger size will improve the precision of the CONREC algorithm,
   but will slow down the time that is needed to calculate the lines.

   The default implementation returns rect.size() / 2 bounded to
   the resolution depending on pixelSize().

   \param area Rectangle, where to calculate the contour lines
   \param rect Rectangle in pixel coordinates, where to paint the contour lines
   \return Raster to be used by the CONREC contour algorithm.

   \note The size will be bounded to rect.size().

   \sa drawContourLines(), QwtRasterData::contourLines()
*/
QSize QwtPlotSpectrogram::contourRasterSize( 
    const QRectF &area, const QRect &rect ) const
{
    QSize raster = rect.size() / 2;

    const QRectF pixelRect = pixelHint( area );
    if ( !pixelRect.isEmpty() )
    {
        const QSize res( qCeil( rect.width() / pixelRect.width() ),
            qCeil( rect.height() / pixelRect.height() ) );
        raster = raster.boundedTo( res );
    }

    return raster;
}
Example #2
0
/*!
  \brief Draw the raster data
  \param painter Painter
  \param xMap X-Scale Map
  \param yMap Y-Scale Map
  \param canvasRect Contents rectangle of the plot canvas
*/
void QwtPlotRasterItem::draw( QPainter *painter,
    const QwtScaleMap &xMap, const QwtScaleMap &yMap,
    const QRectF &canvasRect ) const
{
    if ( canvasRect.isEmpty() || d_data->alpha == 0 )
        return;

    const bool doCache = qwtUseCache( d_data->cache.policy, painter );

    const QwtInterval xInterval = interval( Qt::XAxis );
    const QwtInterval yInterval = interval( Qt::YAxis );

    /*
        Scaling an image always results in a loss of
        precision/quality. So we always render the image in
        paint device resolution.
    */

    QwtScaleMap xxMap, yyMap;
    qwtTransformMaps( painter->transform(), xMap, yMap, xxMap, yyMap );

    QRectF paintRect = painter->transform().mapRect( canvasRect );
    QRectF area = QwtScaleMap::invTransform( xxMap, yyMap, paintRect );

    const QRectF br = boundingRect();
    if ( br.isValid() && !br.contains( area ) )
    {
        area &= br;
        if ( !area.isValid() )
            return;

        paintRect = QwtScaleMap::transform( xxMap, yyMap, area );
    }

    QRectF imageRect;
    QImage image;

    QRectF pixelRect = pixelHint(area);
    if ( !pixelRect.isEmpty() )
    {
        // pixel in target device resolution 
        const double dx = qAbs( xxMap.invTransform( 1 ) - xxMap.invTransform( 0 ) );
        const double dy = qAbs( yyMap.invTransform( 1 ) - yyMap.invTransform( 0 ) );

        if ( dx > pixelRect.width() && dy > pixelRect.height() )
        {
            /*
              When the resolution of the data pixels is higher than
              the resolution of the target device we render in
              target device resolution.
             */
            pixelRect = QRectF();
        }
    }

    if ( pixelRect.isEmpty() )
    {
        if ( QwtPainter::roundingAlignment( painter ) )
        {
            // we want to have maps, where the boundaries of
            // the aligned paint rectangle exactly match the area

            paintRect = qwtAlignRect(paintRect);
            qwtAdjustMaps(xxMap, yyMap, area, paintRect);
        }

        // When we have no information about position and size of
        // data pixels we render in resolution of the paint device.

        image = compose(xxMap, yyMap, 
            area, paintRect, paintRect.size().toSize(), doCache);
        if ( image.isNull() )
            return;

        // Remove pixels at the boundaries, when explicitly
        // excluded in the intervals

        imageRect = qwtStripRect(paintRect, area, 
            xxMap, yyMap, xInterval, yInterval);

        if ( imageRect != paintRect )
        {
            const QRect r( 
                qRound( imageRect.x() - paintRect.x()),
                qRound( imageRect.y() - paintRect.y() ),
                qRound( imageRect.width() ),
                qRound( imageRect.height() ) );
                
            image = image.copy(r);
        }   
    }
    else
    {
        if ( QwtPainter::roundingAlignment( painter ) )
            paintRect = qwtAlignRect(paintRect);

        // align the area to the data pixels
        QRectF imageArea = qwtExpandToPixels(area, pixelRect);

        if ( imageArea.right() == xInterval.maxValue() &&
            !( xInterval.borderFlags() & QwtInterval::ExcludeMaximum ) )
        {
            imageArea.adjust(0, 0, pixelRect.width(), 0);
        }
        if ( imageArea.bottom() == yInterval.maxValue() &&
            !( yInterval.borderFlags() & QwtInterval::ExcludeMaximum ) )
        {
            imageArea.adjust(0, 0, 0, pixelRect.height() );
        }

        QSize imageSize;
        imageSize.setWidth( qRound( imageArea.width() / pixelRect.width() ) );
        imageSize.setHeight( qRound( imageArea.height() / pixelRect.height() ) );
        image = compose(xxMap, yyMap, 
            imageArea, paintRect, imageSize, doCache );
        if ( image.isNull() )
            return;

        imageRect = qwtStripRect(paintRect, area, 
            xxMap, yyMap, xInterval, yInterval);

        if ( ( image.width() > 1 || image.height() > 1 ) &&
            testPaintAttribute( PaintInDeviceResolution ) )
        {
            // Because of rounding errors the pixels 
            // need to be expanded manually to rectangles of 
            // different sizes

            image = qwtExpandImage(image, xxMap, yyMap, 
                imageArea, area, paintRect, xInterval, yInterval );
        }
    }

    painter->save();
    painter->setWorldTransform( QTransform() );
    
    QwtPainter::drawImage( painter, imageRect, image );

    painter->restore();
}