qwt_plot_intervalcurve.cpp
Go to the documentation of this file.
00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 #include "qwt_plot_intervalcurve.h"
00011 #include "qwt_interval_symbol.h"
00012 #include "qwt_scale_map.h"
00013 #include "qwt_clipper.h"
00014 #include "qwt_painter.h"
00015 #include <string.h>
00016 
00017 #include <qpainter.h>
00018 
00019 static inline bool qwtIsHSampleInside( const QwtIntervalSample &sample,
00020     double xMin, double xMax, double yMin, double yMax )
00021 {
00022     const double y = sample.value;
00023     const double x1 = sample.interval.minValue();
00024     const double x2 = sample.interval.maxValue();
00025 
00026     const bool isOffScreen = ( y < yMin ) || ( y > yMax )
00027         || ( x1 < xMin && x2 < xMin ) || ( x1 > xMax && x2 > xMax );
00028 
00029     return !isOffScreen;
00030 }
00031 
00032 static inline bool qwtIsVSampleInside( const QwtIntervalSample &sample,
00033     double xMin, double xMax, double yMin, double yMax )
00034 {
00035     const double x = sample.value;
00036     const double y1 = sample.interval.minValue();
00037     const double y2 = sample.interval.maxValue();
00038 
00039     const bool isOffScreen = ( x < xMin ) || ( x > xMax )
00040         || ( y1 < yMin && y2 < yMin ) || ( y1 > yMax && y2 > yMax );
00041 
00042     return !isOffScreen;
00043 }
00044 
00045 class QwtPlotIntervalCurve::PrivateData
00046 {
00047 public:
00048     PrivateData():
00049         style( QwtPlotIntervalCurve::Tube ),
00050         symbol( NULL ),
00051         pen( Qt::black ),
00052         brush( Qt::white )
00053     {
00054         paintAttributes = QwtPlotIntervalCurve::ClipPolygons;
00055         paintAttributes |= QwtPlotIntervalCurve::ClipSymbol;
00056 
00057         pen.setCapStyle( Qt::FlatCap );
00058     }
00059 
00060     ~PrivateData()
00061     {
00062         delete symbol;
00063     }
00064 
00065     QwtPlotIntervalCurve::CurveStyle style;
00066     const QwtIntervalSymbol *symbol;
00067 
00068     QPen pen;
00069     QBrush brush;
00070 
00071     QwtPlotIntervalCurve::PaintAttributes paintAttributes;
00072 };
00073 
00078 QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QwtText &title ):
00079     QwtPlotSeriesItem( title )
00080 {
00081     init();
00082 }
00083 
00088 QwtPlotIntervalCurve::QwtPlotIntervalCurve( const QString &title ):
00089     QwtPlotSeriesItem( QwtText( title ) )
00090 {
00091     init();
00092 }
00093 
00095 QwtPlotIntervalCurve::~QwtPlotIntervalCurve()
00096 {
00097     delete d_data;
00098 }
00099 
00101 void QwtPlotIntervalCurve::init()
00102 {
00103     setItemAttribute( QwtPlotItem::Legend, true );
00104     setItemAttribute( QwtPlotItem::AutoScale, true );
00105 
00106     d_data = new PrivateData;
00107     setData( new QwtIntervalSeriesData() );
00108 
00109     setZ( 19.0 );
00110 }
00111 
00113 int QwtPlotIntervalCurve::rtti() const
00114 {
00115     return QwtPlotIntervalCurve::Rtti_PlotIntervalCurve;
00116 }
00117 
00125 void QwtPlotIntervalCurve::setPaintAttribute(
00126     PaintAttribute attribute, bool on )
00127 {
00128     if ( on )
00129         d_data->paintAttributes |= attribute;
00130     else
00131         d_data->paintAttributes &= ~attribute;
00132 }
00133 
00138 bool QwtPlotIntervalCurve::testPaintAttribute(
00139     PaintAttribute attribute ) const
00140 {
00141     return ( d_data->paintAttributes & attribute );
00142 }
00143 
00148 void QwtPlotIntervalCurve::setSamples(
00149     const QVector<QwtIntervalSample> &samples )
00150 {
00151     setData( new QwtIntervalSeriesData( samples ) );
00152 }
00153 
00164 void QwtPlotIntervalCurve::setSamples( 
00165     QwtSeriesData<QwtIntervalSample> *data )
00166 {
00167     setData( data );
00168 }
00169 
00176 void QwtPlotIntervalCurve::setStyle( CurveStyle style )
00177 {
00178     if ( style != d_data->style )
00179     {
00180         d_data->style = style;
00181 
00182         legendChanged();
00183         itemChanged();
00184     }
00185 }
00186 
00191 QwtPlotIntervalCurve::CurveStyle QwtPlotIntervalCurve::style() const
00192 {
00193     return d_data->style;
00194 }
00195 
00202 void QwtPlotIntervalCurve::setSymbol( const QwtIntervalSymbol *symbol )
00203 {
00204     if ( symbol != d_data->symbol )
00205     {
00206         delete d_data->symbol;
00207         d_data->symbol = symbol;
00208 
00209         legendChanged();
00210         itemChanged();
00211     }
00212 }
00213 
00218 const QwtIntervalSymbol *QwtPlotIntervalCurve::symbol() const
00219 {
00220     return d_data->symbol;
00221 }
00222 
00236 void QwtPlotIntervalCurve::setPen( const QColor &color, qreal width, Qt::PenStyle style )
00237 {   
00238     setPen( QPen( color, width, style ) );
00239 }   
00240 
00246 void QwtPlotIntervalCurve::setPen( const QPen &pen )
00247 {
00248     if ( pen != d_data->pen )
00249     {
00250         d_data->pen = pen;
00251 
00252         legendChanged();
00253         itemChanged();
00254     }
00255 }
00256 
00261 const QPen& QwtPlotIntervalCurve::pen() const
00262 {
00263     return d_data->pen;
00264 }
00265 
00274 void QwtPlotIntervalCurve::setBrush( const QBrush &brush )
00275 {
00276     if ( brush != d_data->brush )
00277     {
00278         d_data->brush = brush;
00279 
00280         legendChanged();
00281         itemChanged();
00282     }
00283 }
00284 
00289 const QBrush& QwtPlotIntervalCurve::brush() const
00290 {
00291     return d_data->brush;
00292 }
00293 
00298 QRectF QwtPlotIntervalCurve::boundingRect() const
00299 {
00300     QRectF rect = QwtPlotSeriesItem::boundingRect();
00301     if ( rect.isValid() && orientation() == Qt::Vertical )
00302         rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() );
00303 
00304     return rect;
00305 }
00306 
00320 void QwtPlotIntervalCurve::drawSeries( QPainter *painter,
00321     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00322     const QRectF &canvasRect, int from, int to ) const
00323 {
00324     if ( to < 0 )
00325         to = dataSize() - 1;
00326 
00327     if ( from < 0 )
00328         from = 0;
00329 
00330     if ( from > to )
00331         return;
00332 
00333     switch ( d_data->style )
00334     {
00335         case Tube:
00336             drawTube( painter, xMap, yMap, canvasRect, from, to );
00337             break;
00338 
00339         case NoCurve:
00340         default:
00341             break;
00342     }
00343 
00344     if ( d_data->symbol &&
00345         ( d_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) )
00346     {
00347         drawSymbols( painter, *d_data->symbol,
00348             xMap, yMap, canvasRect, from, to );
00349     }
00350 }
00351 
00369 void QwtPlotIntervalCurve::drawTube( QPainter *painter,
00370     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00371     const QRectF &canvasRect, int from, int to ) const
00372 {
00373     const bool doAlign = QwtPainter::roundingAlignment( painter );
00374 
00375     painter->save();
00376 
00377     const size_t size = to - from + 1;
00378     QPolygonF polygon( 2 * size );
00379     QPointF *points = polygon.data();
00380 
00381     for ( uint i = 0; i < size; i++ )
00382     {
00383         QPointF &minValue = points[i];
00384         QPointF &maxValue = points[2 * size - 1 - i];
00385 
00386         const QwtIntervalSample intervalSample = sample( from + i );
00387         if ( orientation() == Qt::Vertical )
00388         {
00389             double x = xMap.transform( intervalSample.value );
00390             double y1 = yMap.transform( intervalSample.interval.minValue() );
00391             double y2 = yMap.transform( intervalSample.interval.maxValue() );
00392             if ( doAlign )
00393             {
00394                 x = qRound( x );
00395                 y1 = qRound( y1 );
00396                 y2 = qRound( y2 );
00397             }
00398 
00399             minValue.rx() = x;
00400             minValue.ry() = y1;
00401             maxValue.rx() = x;
00402             maxValue.ry() = y2;
00403         }
00404         else
00405         {
00406             double y = yMap.transform( intervalSample.value );
00407             double x1 = xMap.transform( intervalSample.interval.minValue() );
00408             double x2 = xMap.transform( intervalSample.interval.maxValue() );
00409             if ( doAlign )
00410             {
00411                 y = qRound( y );
00412                 x1 = qRound( x1 );
00413                 x2 = qRound( x2 );
00414             }
00415 
00416             minValue.rx() = x1;
00417             minValue.ry() = y;
00418             maxValue.rx() = x2;
00419             maxValue.ry() = y;
00420         }
00421     }
00422 
00423     if ( d_data->brush.style() != Qt::NoBrush )
00424     {
00425         painter->setPen( QPen( Qt::NoPen ) );
00426         painter->setBrush( d_data->brush );
00427 
00428         if ( d_data->paintAttributes & ClipPolygons )
00429         {
00430             const qreal m = 1.0;
00431             const QPolygonF p = QwtClipper::clipPolygonF(
00432                canvasRect.adjusted( -m, -m, m, m ), polygon, true );
00433 
00434             QwtPainter::drawPolygon( painter, p );
00435         }
00436         else
00437         {
00438             QwtPainter::drawPolygon( painter, polygon );
00439         }
00440     }
00441 
00442     if ( d_data->pen.style() != Qt::NoPen )
00443     {
00444         painter->setPen( d_data->pen );
00445         painter->setBrush( Qt::NoBrush );
00446 
00447         if ( d_data->paintAttributes & ClipPolygons )
00448         {
00449             qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF() );
00450             const QRectF clipRect = canvasRect.adjusted( -pw, -pw, pw, pw );
00451 
00452             QPolygonF p;
00453 
00454             p.resize( size );
00455             ::memcpy( p.data(), points, size * sizeof( QPointF ) );
00456             p = QwtClipper::clipPolygonF( clipRect, p );
00457             QwtPainter::drawPolyline( painter, p );
00458 
00459             p.resize( size );
00460             ::memcpy( p.data(), points + size, size * sizeof( QPointF ) );
00461             p = QwtClipper::clipPolygonF( clipRect, p );
00462             QwtPainter::drawPolyline( painter, p );
00463         }
00464         else
00465         {
00466             QwtPainter::drawPolyline( painter, points, size );
00467             QwtPainter::drawPolyline( painter, points + size, size );
00468         }
00469     }
00470 
00471     painter->restore();
00472 }
00473 
00487 void QwtPlotIntervalCurve::drawSymbols(
00488     QPainter *painter, const QwtIntervalSymbol &symbol,
00489     const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00490     const QRectF &canvasRect, int from, int to ) const
00491 {
00492     painter->save();
00493 
00494     QPen pen = symbol.pen();
00495     pen.setCapStyle( Qt::FlatCap );
00496 
00497     painter->setPen( pen );
00498     painter->setBrush( symbol.brush() );
00499 
00500     const QRectF tr = QwtScaleMap::invTransform( xMap, yMap, canvasRect );
00501 
00502     const double xMin = tr.left();
00503     const double xMax = tr.right();
00504     const double yMin = tr.top();
00505     const double yMax = tr.bottom();
00506 
00507     const bool doClip = d_data->paintAttributes & ClipSymbol;
00508 
00509     for ( int i = from; i <= to; i++ )
00510     {
00511         const QwtIntervalSample s = sample( i );
00512 
00513         if ( orientation() == Qt::Vertical )
00514         {
00515             if ( !doClip || qwtIsVSampleInside( s, xMin, xMax, yMin, yMax ) )
00516             {
00517                 const double x = xMap.transform( s.value );
00518                 const double y1 = yMap.transform( s.interval.minValue() );
00519                 const double y2 = yMap.transform( s.interval.maxValue() );
00520 
00521                 symbol.draw( painter, orientation(),
00522                     QPointF( x, y1 ), QPointF( x, y2 ) );
00523             }
00524         }
00525         else
00526         {
00527             if ( !doClip || qwtIsHSampleInside( s, xMin, xMax, yMin, yMax ) )
00528             {
00529                 const double y = yMap.transform( s.value );
00530                 const double x1 = xMap.transform( s.interval.minValue() );
00531                 const double x2 = xMap.transform( s.interval.maxValue() );
00532 
00533                 symbol.draw( painter, orientation(),
00534                     QPointF( x1, y ), QPointF( x2, y ) );
00535             }
00536         }
00537     }
00538 
00539     painter->restore();
00540 }
00541 
00554 QwtGraphic QwtPlotIntervalCurve::legendIcon( 
00555     int index, const QSizeF &size ) const
00556 {
00557     Q_UNUSED( index );
00558 
00559     if ( size.isEmpty() )
00560         return QwtGraphic();
00561 
00562     QwtGraphic icon;
00563     icon.setDefaultSize( size );
00564     icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true );
00565 
00566     QPainter painter( &icon );
00567     painter.setRenderHint( QPainter::Antialiasing,
00568         testRenderHint( QwtPlotItem::RenderAntialiased ) );
00569 
00570     if ( d_data->style == Tube )
00571     {
00572         QRectF r( 0, 0, size.width(), size.height() );
00573         painter.fillRect( r, d_data->brush );
00574     }
00575 
00576     if ( d_data->symbol &&
00577         ( d_data->symbol->style() != QwtIntervalSymbol::NoSymbol ) )
00578     {
00579         QPen pen = d_data->symbol->pen();
00580         pen.setWidthF( pen.widthF() );
00581         pen.setCapStyle( Qt::FlatCap );
00582 
00583         painter.setPen( pen );
00584         painter.setBrush( d_data->symbol->brush() );
00585 
00586         if ( orientation() == Qt::Vertical )
00587         {
00588             const double x = 0.5 * size.width();
00589 
00590             d_data->symbol->draw( &painter, orientation(),
00591                 QPointF( x, 0 ), QPointF( x, size.height() - 1.0 ) );
00592         }
00593         else
00594         {
00595             const double y = 0.5 * size.height();
00596 
00597             d_data->symbol->draw( &painter, orientation(),
00598                 QPointF( 0.0, y ), QPointF( size.width() - 1.0, y ) );
00599         }
00600     }
00601 
00602     return icon;
00603 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:56