Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_plot_shapeitem.h"
00011 #include "qwt_scale_map.h"
00012 #include "qwt_painter.h"
00013 #include "qwt_weeding_curve_fitter.h"
00014 #include "qwt_clipper.h"
00015
00016 static QPainterPath qwtTransformPath( const QwtScaleMap &xMap,
00017 const QwtScaleMap &yMap, const QPainterPath &path, bool doAlign )
00018 {
00019 QPainterPath shape;
00020 shape.setFillRule( path.fillRule() );
00021
00022 for ( int i = 0; i < path.elementCount(); i++ )
00023 {
00024 const QPainterPath::Element &element = path.elementAt( i );
00025
00026 double x = xMap.transform( element.x );
00027 double y = yMap.transform( element.y );
00028
00029 switch( element.type )
00030 {
00031 case QPainterPath::MoveToElement:
00032 {
00033 if ( doAlign )
00034 {
00035 x = qRound( x );
00036 y = qRound( y );
00037 }
00038
00039 shape.moveTo( x, y );
00040 break;
00041 }
00042 case QPainterPath::LineToElement:
00043 {
00044 if ( doAlign )
00045 {
00046 x = qRound( x );
00047 y = qRound( y );
00048 }
00049
00050 shape.lineTo( x, y );
00051 break;
00052 }
00053 case QPainterPath::CurveToElement:
00054 {
00055 const QPainterPath::Element& element1 = path.elementAt( ++i );
00056 const double x1 = xMap.transform( element1.x );
00057 const double y1 = yMap.transform( element1.y );
00058
00059 const QPainterPath::Element& element2 = path.elementAt( ++i );
00060 const double x2 = xMap.transform( element2.x );
00061 const double y2 = yMap.transform( element2.y );
00062
00063 shape.cubicTo( x, y, x1, y1, x2, y2 );
00064 break;
00065 }
00066 case QPainterPath::CurveToDataElement:
00067 {
00068 break;
00069 }
00070 }
00071 }
00072
00073 return shape;
00074 }
00075
00076
00077 class QwtPlotShapeItem::PrivateData
00078 {
00079 public:
00080 PrivateData():
00081 legendMode( QwtPlotShapeItem::LegendColor ),
00082 renderTolerance( 0.0 )
00083 {
00084 }
00085
00086 QwtPlotShapeItem::PaintAttributes paintAttributes;
00087 QwtPlotShapeItem::LegendMode legendMode;
00088
00089 double renderTolerance;
00090 QRectF boundingRect;
00091
00092 QPen pen;
00093 QBrush brush;
00094 QPainterPath shape;
00095 };
00096
00106 QwtPlotShapeItem::QwtPlotShapeItem( const QString& title ):
00107 QwtPlotItem( QwtText( title ) )
00108 {
00109 init();
00110 }
00111
00121 QwtPlotShapeItem::QwtPlotShapeItem( const QwtText& title ):
00122 QwtPlotItem( title )
00123 {
00124 init();
00125 }
00126
00128 QwtPlotShapeItem::~QwtPlotShapeItem()
00129 {
00130 delete d_data;
00131 }
00132
00133 void QwtPlotShapeItem::init()
00134 {
00135 d_data = new PrivateData();
00136 d_data->boundingRect = QwtPlotItem::boundingRect();
00137
00138 setItemAttribute( QwtPlotItem::AutoScale, true );
00139 setItemAttribute( QwtPlotItem::Legend, false );
00140
00141 setZ( 8.0 );
00142 }
00143
00145 int QwtPlotShapeItem::rtti() const
00146 {
00147 return QwtPlotItem::Rtti_PlotShape;
00148 }
00149
00157 void QwtPlotShapeItem::setPaintAttribute( PaintAttribute attribute, bool on )
00158 {
00159 if ( on )
00160 d_data->paintAttributes |= attribute;
00161 else
00162 d_data->paintAttributes &= ~attribute;
00163 }
00164
00169 bool QwtPlotShapeItem::testPaintAttribute( PaintAttribute attribute ) const
00170 {
00171 return ( d_data->paintAttributes & attribute );
00172 }
00173
00180 void QwtPlotShapeItem::setLegendMode( LegendMode mode )
00181 {
00182 if ( mode != d_data->legendMode )
00183 {
00184 d_data->legendMode = mode;
00185 legendChanged();
00186 }
00187 }
00188
00193 QwtPlotShapeItem::LegendMode QwtPlotShapeItem::legendMode() const
00194 {
00195 return d_data->legendMode;
00196 }
00197
00199 QRectF QwtPlotShapeItem::boundingRect() const
00200 {
00201 return d_data->boundingRect;
00202 }
00203
00210 void QwtPlotShapeItem::setRect( const QRectF &rect )
00211 {
00212 QPainterPath path;
00213 path.addRect( rect );
00214
00215 setShape( path );
00216 }
00217
00224 void QwtPlotShapeItem::setPolygon( const QPolygonF &polygon )
00225 {
00226 QPainterPath shape;
00227 shape.addPolygon( polygon );
00228
00229 setShape( shape );
00230 }
00231
00238 void QwtPlotShapeItem::setShape( const QPainterPath &shape )
00239 {
00240 if ( shape != d_data->shape )
00241 {
00242 d_data->shape = shape;
00243 if ( shape.isEmpty() )
00244 {
00245 d_data->boundingRect = QwtPlotItem::boundingRect();
00246 }
00247 else
00248 {
00249 d_data->boundingRect = shape.boundingRect();
00250 }
00251
00252 itemChanged();
00253 }
00254 }
00255
00260 QPainterPath QwtPlotShapeItem::shape() const
00261 {
00262 return d_data->shape;
00263 }
00264
00278 void QwtPlotShapeItem::setPen( const QColor &color, qreal width, Qt::PenStyle style )
00279 {
00280 setPen( QPen( color, width, style ) );
00281 }
00282
00291 void QwtPlotShapeItem::setPen( const QPen &pen )
00292 {
00293 if ( pen != d_data->pen )
00294 {
00295 d_data->pen = pen;
00296 itemChanged();
00297 }
00298 }
00299
00304 QPen QwtPlotShapeItem::pen() const
00305 {
00306 return d_data->pen;
00307 }
00308
00317 void QwtPlotShapeItem::setBrush( const QBrush &brush )
00318 {
00319 if ( brush != d_data->brush )
00320 {
00321 d_data->brush = brush;
00322 itemChanged();
00323 }
00324 }
00325
00330 QBrush QwtPlotShapeItem::brush() const
00331 {
00332 return d_data->brush;
00333 }
00334
00351 void QwtPlotShapeItem::setRenderTolerance( double tolerance )
00352 {
00353 tolerance = qMax( tolerance, 0.0 );
00354
00355 if ( tolerance != d_data->renderTolerance )
00356 {
00357 d_data->renderTolerance = tolerance;
00358 itemChanged();
00359 }
00360 }
00361
00366 double QwtPlotShapeItem::renderTolerance() const
00367 {
00368 return d_data->renderTolerance;
00369 }
00370
00379 void QwtPlotShapeItem::draw( QPainter *painter,
00380 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00381 const QRectF &canvasRect ) const
00382 {
00383 if ( d_data->shape.isEmpty() )
00384 return;
00385
00386 if ( d_data->pen.style() == Qt::NoPen
00387 && d_data->brush.style() == Qt::NoBrush )
00388 {
00389 return;
00390 }
00391
00392 const QRectF cr = QwtScaleMap::invTransform(
00393 xMap, yMap, canvasRect.toRect() );
00394
00395 const QRectF &br = d_data->boundingRect;
00396
00397 if ( ( br.left() > cr.right() ) || ( br.right() < cr.left() )
00398 || ( br.top() > cr.bottom() ) || ( br.bottom() < cr.top() ) )
00399 {
00400
00401 return;
00402 }
00403
00404 const bool doAlign = QwtPainter::roundingAlignment( painter );
00405
00406 QPainterPath path = qwtTransformPath( xMap, yMap,
00407 d_data->shape, doAlign );
00408
00409 if ( testPaintAttribute( QwtPlotShapeItem::ClipPolygons ) )
00410 {
00411 qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF());
00412 QRectF clipRect = canvasRect.adjusted( -pw, -pw, pw, pw );
00413
00414 QPainterPath clippedPath;
00415 clippedPath.setFillRule( path.fillRule() );
00416
00417 const QList<QPolygonF> polygons = path.toSubpathPolygons();
00418 for ( int i = 0; i < polygons.size(); i++ )
00419 {
00420 const QPolygonF p = QwtClipper::clipPolygonF(
00421 clipRect, polygons[i], true );
00422
00423 clippedPath.addPolygon( p );
00424
00425 }
00426
00427 path = clippedPath;
00428 }
00429
00430 if ( d_data->renderTolerance > 0.0 )
00431 {
00432 QwtWeedingCurveFitter fitter( d_data->renderTolerance );
00433
00434 QPainterPath fittedPath;
00435 fittedPath.setFillRule( path.fillRule() );
00436
00437 const QList<QPolygonF> polygons = path.toSubpathPolygons();
00438 for ( int i = 0; i < polygons.size(); i++ )
00439 fittedPath.addPolygon( fitter.fitCurve( polygons[ i ] ) );
00440
00441 path = fittedPath;
00442 }
00443
00444 painter->setPen( d_data->pen );
00445 painter->setBrush( d_data->brush );
00446
00447 painter->drawPath( path );
00448 }
00449
00459 QwtGraphic QwtPlotShapeItem::legendIcon( int index,
00460 const QSizeF &size ) const
00461 {
00462 Q_UNUSED( index );
00463
00464 QwtGraphic icon;
00465 icon.setDefaultSize( size );
00466
00467 if ( size.isEmpty() )
00468 return icon;
00469
00470 if ( d_data->legendMode == QwtPlotShapeItem::LegendShape )
00471 {
00472 const QRectF &br = d_data->boundingRect;
00473
00474 QPainter painter( &icon );
00475 painter.setRenderHint( QPainter::Antialiasing,
00476 testRenderHint( QwtPlotItem::RenderAntialiased ) );
00477
00478 painter.translate( -br.topLeft() );
00479
00480 painter.setPen( d_data->pen );
00481 painter.setBrush( d_data->brush );
00482 painter.drawPath( d_data->shape );
00483 }
00484 else
00485 {
00486 QColor iconColor;
00487 if ( d_data->brush.style() != Qt::NoBrush )
00488 iconColor = d_data->brush.color();
00489 else
00490 iconColor = d_data->pen.color();
00491
00492 icon = defaultIcon( iconColor, size );
00493 }
00494
00495 return icon;
00496 }
00497