00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_plot_curve.h"
00011 #include "qwt_point_data.h"
00012 #include "qwt_math.h"
00013 #include "qwt_clipper.h"
00014 #include "qwt_painter.h"
00015 #include "qwt_scale_map.h"
00016 #include "qwt_plot.h"
00017 #include "qwt_spline_curve_fitter.h"
00018 #include "qwt_symbol.h"
00019 #include "qwt_point_mapper.h"
00020 #include <qpainter.h>
00021 #include <qpixmap.h>
00022 #include <qalgorithms.h>
00023 #include <qmath.h>
00024
00025 static inline QRectF qwtIntersectedClipRect( const QRectF &rect, QPainter *painter )
00026 {
00027 QRectF clipRect = rect;
00028 if ( painter->hasClipping() )
00029 {
00030 #if QT_VERSION >= 0x040800
00031 const QRectF r = painter->clipBoundingRect();
00032 #else
00033 const QRectF r = painter->clipRegion().boundingRect();
00034 #endif
00035 clipRect &= r;
00036 }
00037
00038 return clipRect;
00039 }
00040
00041 static void qwtUpdateLegendIconSize( QwtPlotCurve *curve )
00042 {
00043 if ( curve->symbol() &&
00044 curve->testLegendAttribute( QwtPlotCurve::LegendShowSymbol ) )
00045 {
00046 QSize sz = curve->symbol()->boundingRect().size();
00047 sz += QSize( 2, 2 );
00048
00049 if ( curve->testLegendAttribute( QwtPlotCurve::LegendShowLine ) )
00050 {
00051
00052
00053 int w = qCeil( 1.5 * sz.width() );
00054 if ( w % 2 )
00055 w++;
00056
00057 sz.setWidth( qMax( 8, w ) );
00058 }
00059
00060 curve->setLegendIconSize( sz );
00061 }
00062 }
00063
00064 static int qwtVerifyRange( int size, int &i1, int &i2 )
00065 {
00066 if ( size < 1 )
00067 return 0;
00068
00069 i1 = qBound( 0, i1, size - 1 );
00070 i2 = qBound( 0, i2, size - 1 );
00071
00072 if ( i1 > i2 )
00073 qSwap( i1, i2 );
00074
00075 return ( i2 - i1 + 1 );
00076 }
00077
00078 class QwtPlotCurve::PrivateData
00079 {
00080 public:
00081 PrivateData():
00082 style( QwtPlotCurve::Lines ),
00083 baseline( 0.0 ),
00084 symbol( NULL ),
00085 pen( Qt::black ),
00086 attributes( 0 ),
00087 paintAttributes(
00088 QwtPlotCurve::ClipPolygons | QwtPlotCurve::FilterPoints ),
00089 legendAttributes( 0 )
00090 {
00091 curveFitter = new QwtSplineCurveFitter;
00092 }
00093
00094 ~PrivateData()
00095 {
00096 delete symbol;
00097 delete curveFitter;
00098 }
00099
00100 QwtPlotCurve::CurveStyle style;
00101 double baseline;
00102
00103 const QwtSymbol *symbol;
00104 QwtCurveFitter *curveFitter;
00105
00106 QPen pen;
00107 QBrush brush;
00108
00109 QwtPlotCurve::CurveAttributes attributes;
00110 QwtPlotCurve::PaintAttributes paintAttributes;
00111
00112 QwtPlotCurve::LegendAttributes legendAttributes;
00113 };
00114
00119 QwtPlotCurve::QwtPlotCurve( const QwtText &title ):
00120 QwtPlotSeriesItem( title )
00121 {
00122 init();
00123 }
00124
00129 QwtPlotCurve::QwtPlotCurve( const QString &title ):
00130 QwtPlotSeriesItem( QwtText( title ) )
00131 {
00132 init();
00133 }
00134
00136 QwtPlotCurve::~QwtPlotCurve()
00137 {
00138 delete d_data;
00139 }
00140
00142 void QwtPlotCurve::init()
00143 {
00144 setItemAttribute( QwtPlotItem::Legend );
00145 setItemAttribute( QwtPlotItem::AutoScale );
00146
00147 d_data = new PrivateData;
00148 setData( new QwtPointSeriesData() );
00149
00150 setZ( 20.0 );
00151 }
00152
00154 int QwtPlotCurve::rtti() const
00155 {
00156 return QwtPlotItem::Rtti_PlotCurve;
00157 }
00158
00166 void QwtPlotCurve::setPaintAttribute( PaintAttribute attribute, bool on )
00167 {
00168 if ( on )
00169 d_data->paintAttributes |= attribute;
00170 else
00171 d_data->paintAttributes &= ~attribute;
00172 }
00173
00178 bool QwtPlotCurve::testPaintAttribute( PaintAttribute attribute ) const
00179 {
00180 return ( d_data->paintAttributes & attribute );
00181 }
00182
00190 void QwtPlotCurve::setLegendAttribute( LegendAttribute attribute, bool on )
00191 {
00192 if ( on != testLegendAttribute( attribute ) )
00193 {
00194 if ( on )
00195 d_data->legendAttributes |= attribute;
00196 else
00197 d_data->legendAttributes &= ~attribute;
00198
00199 qwtUpdateLegendIconSize( this );
00200 legendChanged();
00201 }
00202 }
00203
00208 bool QwtPlotCurve::testLegendAttribute( LegendAttribute attribute ) const
00209 {
00210 return ( d_data->legendAttributes & attribute );
00211 }
00212
00219 void QwtPlotCurve::setStyle( CurveStyle style )
00220 {
00221 if ( style != d_data->style )
00222 {
00223 d_data->style = style;
00224
00225 legendChanged();
00226 itemChanged();
00227 }
00228 }
00229
00234 QwtPlotCurve::CurveStyle QwtPlotCurve::style() const
00235 {
00236 return d_data->style;
00237 }
00238
00249 void QwtPlotCurve::setSymbol( QwtSymbol *symbol )
00250 {
00251 if ( symbol != d_data->symbol )
00252 {
00253 delete d_data->symbol;
00254 d_data->symbol = symbol;
00255
00256 qwtUpdateLegendIconSize( this );
00257
00258 legendChanged();
00259 itemChanged();
00260 }
00261 }
00262
00267 const QwtSymbol *QwtPlotCurve::symbol() const
00268 {
00269 return d_data->symbol;
00270 }
00271
00285 void QwtPlotCurve::setPen( const QColor &color, qreal width, Qt::PenStyle style )
00286 {
00287 setPen( QPen( color, width, style ) );
00288 }
00289
00296 void QwtPlotCurve::setPen( const QPen &pen )
00297 {
00298 if ( pen != d_data->pen )
00299 {
00300 d_data->pen = pen;
00301
00302 legendChanged();
00303 itemChanged();
00304 }
00305 }
00306
00311 const QPen& QwtPlotCurve::pen() const
00312 {
00313 return d_data->pen;
00314 }
00315
00331 void QwtPlotCurve::setBrush( const QBrush &brush )
00332 {
00333 if ( brush != d_data->brush )
00334 {
00335 d_data->brush = brush;
00336
00337 legendChanged();
00338 itemChanged();
00339 }
00340 }
00341
00346 const QBrush& QwtPlotCurve::brush() const
00347 {
00348 return d_data->brush;
00349 }
00350
00364 void QwtPlotCurve::drawSeries( QPainter *painter,
00365 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00366 const QRectF &canvasRect, int from, int to ) const
00367 {
00368 const size_t numSamples = dataSize();
00369
00370 if ( !painter || numSamples <= 0 )
00371 return;
00372
00373 if ( to < 0 )
00374 to = numSamples - 1;
00375
00376 if ( qwtVerifyRange( numSamples, from, to ) > 0 )
00377 {
00378 painter->save();
00379 painter->setPen( d_data->pen );
00380
00381
00382
00383
00384
00385
00386
00387 drawCurve( painter, d_data->style, xMap, yMap, canvasRect, from, to );
00388 painter->restore();
00389
00390 if ( d_data->symbol &&
00391 ( d_data->symbol->style() != QwtSymbol::NoSymbol ) )
00392 {
00393 painter->save();
00394 drawSymbols( painter, *d_data->symbol,
00395 xMap, yMap, canvasRect, from, to );
00396 painter->restore();
00397 }
00398 }
00399 }
00400
00412 void QwtPlotCurve::drawCurve( QPainter *painter, int style,
00413 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00414 const QRectF &canvasRect, int from, int to ) const
00415 {
00416 switch ( style )
00417 {
00418 case Lines:
00419 if ( testCurveAttribute( Fitted ) )
00420 {
00421
00422
00423 from = 0;
00424 to = dataSize() - 1;
00425 }
00426 drawLines( painter, xMap, yMap, canvasRect, from, to );
00427 break;
00428 case Sticks:
00429 drawSticks( painter, xMap, yMap, canvasRect, from, to );
00430 break;
00431 case Steps:
00432 drawSteps( painter, xMap, yMap, canvasRect, from, to );
00433 break;
00434 case Dots:
00435 drawDots( painter, xMap, yMap, canvasRect, from, to );
00436 break;
00437 case LinesAndDots:{
00438
00439 if ( testCurveAttribute( Fitted ) )
00440 {
00441 from = 0;
00442 to = dataSize() - 1;
00443 }
00444 drawLines( painter, xMap, yMap, canvasRect, from, to );
00445
00446 QPen prev_pen = painter->pen();
00447 QPen new_pen = prev_pen;
00448 new_pen.setWidth( prev_pen.width() * 3);
00449
00450 painter->setPen( new_pen );
00451 drawDots( painter, xMap, yMap, canvasRect, from, to );
00452 painter->setPen( prev_pen );
00453 }
00454 break;
00455 case NoCurve:
00456 default:
00457 break;
00458 }
00459 }
00460
00477 void QwtPlotCurve::drawLines( QPainter *painter,
00478 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00479 const QRectF &canvasRect, int from, int to ) const
00480 {
00481 if ( from > to )
00482 return;
00483
00484 const bool doFit = ( d_data->attributes & Fitted ) && d_data->curveFitter;
00485 const bool doAlign = !doFit && QwtPainter::roundingAlignment( painter );
00486 const bool doFill = ( d_data->brush.style() != Qt::NoBrush )
00487 && ( d_data->brush.color().alpha() > 0 );
00488
00489 QRectF clipRect;
00490 if ( d_data->paintAttributes & ClipPolygons )
00491 {
00492 clipRect = qwtIntersectedClipRect( canvasRect, painter );
00493
00494 const qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF());
00495 clipRect = clipRect.adjusted(-pw, -pw, pw, pw);
00496 }
00497
00498 bool doIntegers = false;
00499
00500 #if QT_VERSION < 0x040800
00501 if ( painter->paintEngine()->type() == QPaintEngine::Raster )
00502 {
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 if ( !doFit && !doFill )
00513 doIntegers = true;
00514 }
00515 #endif
00516
00517 QwtPointMapper mapper;
00518
00519 if ( doAlign )
00520 {
00521 mapper.setFlag( QwtPointMapper::RoundPoints, true );
00522 mapper.setFlag( QwtPointMapper::WeedOutIntermediatePoints,
00523 testPaintAttribute( FilterPointsAggressive ) );
00524 }
00525
00526 mapper.setFlag( QwtPointMapper::WeedOutPoints,
00527 testPaintAttribute( FilterPoints ) ||
00528 testPaintAttribute( FilterPointsAggressive ) );
00529
00530 mapper.setBoundingRect( canvasRect );
00531
00532 if ( doIntegers )
00533 {
00534 QPolygon polyline = mapper.toPolygon(
00535 xMap, yMap, data(), from, to );
00536
00537 if ( testPaintAttribute( ClipPolygons ) )
00538 {
00539 polyline = QwtClipper::clipPolygon(
00540 clipRect.toAlignedRect(), polyline, false );
00541 }
00542
00543 QwtPainter::drawPolyline( painter, polyline );
00544 }
00545 else
00546 {
00547 QPolygonF polyline = mapper.toPolygonF( xMap, yMap, data(), from, to );
00548
00549 if ( doFill )
00550 {
00551 if ( doFit )
00552 {
00553
00554
00555
00556
00557 polyline = d_data->curveFitter->fitCurve( polyline );
00558 }
00559
00560 if ( painter->pen().style() != Qt::NoPen )
00561 {
00562
00563
00564
00565 QPolygonF filled = polyline;
00566 fillCurve( painter, xMap, yMap, canvasRect, filled );
00567 filled.clear();
00568
00569 if ( d_data->paintAttributes & ClipPolygons )
00570 polyline = QwtClipper::clipPolygonF( clipRect, polyline, false );
00571
00572 QwtPainter::drawPolyline( painter, polyline );
00573 }
00574 else
00575 {
00576 fillCurve( painter, xMap, yMap, canvasRect, polyline );
00577 }
00578 }
00579 else
00580 {
00581 if ( testPaintAttribute( ClipPolygons ) )
00582 {
00583 polyline = QwtClipper::clipPolygonF(
00584 clipRect, polyline, false );
00585 }
00586
00587 if ( doFit )
00588 {
00589 if ( d_data->curveFitter->mode() == QwtCurveFitter::Path )
00590 {
00591 const QPainterPath curvePath =
00592 d_data->curveFitter->fitCurvePath( polyline );
00593
00594 painter->drawPath( curvePath );
00595 }
00596 else
00597 {
00598 polyline = d_data->curveFitter->fitCurve( polyline );
00599 QwtPainter::drawPolyline( painter, polyline );
00600 }
00601 }
00602 else
00603 {
00604 QwtPainter::drawPolyline( painter, polyline );
00605 }
00606 }
00607 }
00608 }
00609
00622 void QwtPlotCurve::drawSticks( QPainter *painter,
00623 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00624 const QRectF &, int from, int to ) const
00625 {
00626 painter->save();
00627 painter->setRenderHint( QPainter::Antialiasing, false );
00628
00629 const bool doAlign = QwtPainter::roundingAlignment( painter );
00630
00631 double x0 = xMap.transform( d_data->baseline );
00632 double y0 = yMap.transform( d_data->baseline );
00633 if ( doAlign )
00634 {
00635 x0 = qRound( x0 );
00636 y0 = qRound( y0 );
00637 }
00638
00639 const Qt::Orientation o = orientation();
00640
00641 const QwtSeriesData<QPointF> *series = data();
00642
00643 for ( int i = from; i <= to; i++ )
00644 {
00645 const QPointF sample = series->sample( i );
00646 double xi = xMap.transform( sample.x() );
00647 double yi = yMap.transform( sample.y() );
00648 if ( doAlign )
00649 {
00650 xi = qRound( xi );
00651 yi = qRound( yi );
00652 }
00653
00654 if ( o == Qt::Horizontal )
00655 QwtPainter::drawLine( painter, x0, yi, xi, yi );
00656 else
00657 QwtPainter::drawLine( painter, xi, y0, xi, yi );
00658 }
00659
00660 painter->restore();
00661 }
00662
00675 void QwtPlotCurve::drawDots( QPainter *painter,
00676 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00677 const QRectF &canvasRect, int from, int to ) const
00678 {
00679 const QColor color = painter->pen().color();
00680
00681 if ( painter->pen().style() == Qt::NoPen || color.alpha() == 0 )
00682 {
00683 return;
00684 }
00685
00686 const bool doFill = ( d_data->brush.style() != Qt::NoBrush )
00687 && ( d_data->brush.color().alpha() > 0 );
00688 const bool doAlign = QwtPainter::roundingAlignment( painter );
00689
00690 QwtPointMapper mapper;
00691 mapper.setBoundingRect( canvasRect );
00692 mapper.setFlag( QwtPointMapper::RoundPoints, doAlign );
00693
00694 if ( d_data->paintAttributes & FilterPoints )
00695 {
00696 if ( ( color.alpha() == 255 )
00697 && !( painter->renderHints() & QPainter::Antialiasing ) )
00698 {
00699 mapper.setFlag( QwtPointMapper::WeedOutPoints, true );
00700 }
00701 }
00702
00703 if ( doFill )
00704 {
00705 mapper.setFlag( QwtPointMapper::WeedOutPoints, false );
00706
00707 QPolygonF points = mapper.toPointsF(
00708 xMap, yMap, data(), from, to );
00709
00710 QwtPainter::drawPoints( painter, points );
00711 fillCurve( painter, xMap, yMap, canvasRect, points );
00712 }
00713 else if ( d_data->paintAttributes & ImageBuffer )
00714 {
00715 const QImage image = mapper.toImage( xMap, yMap,
00716 data(), from, to, d_data->pen,
00717 painter->testRenderHint( QPainter::Antialiasing ),
00718 renderThreadCount() );
00719
00720 painter->drawImage( canvasRect.toAlignedRect(), image );
00721 }
00722 else if ( d_data->paintAttributes & MinimizeMemory )
00723 {
00724 const QwtSeriesData<QPointF> *series = data();
00725
00726 for ( int i = from; i <= to; i++ )
00727 {
00728 const QPointF sample = series->sample( i );
00729
00730 double xi = xMap.transform( sample.x() );
00731 double yi = yMap.transform( sample.y() );
00732
00733 if ( doAlign )
00734 {
00735 xi = qRound( xi );
00736 yi = qRound( yi );
00737 }
00738
00739 QwtPainter::drawPoint( painter, QPointF( xi, yi ) );
00740 }
00741 }
00742 else
00743 {
00744 if ( doAlign )
00745 {
00746 const QPolygon points = mapper.toPoints(
00747 xMap, yMap, data(), from, to );
00748
00749 QwtPainter::drawPoints( painter, points );
00750 }
00751 else
00752 {
00753 const QPolygonF points = mapper.toPointsF(
00754 xMap, yMap, data(), from, to );
00755
00756 QwtPainter::drawPoints( painter, points );
00757 }
00758 }
00759 }
00760
00776 void QwtPlotCurve::drawSteps( QPainter *painter,
00777 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00778 const QRectF &canvasRect, int from, int to ) const
00779 {
00780 const bool doAlign = QwtPainter::roundingAlignment( painter );
00781
00782 QPolygonF polygon( 2 * ( to - from ) + 1 );
00783 QPointF *points = polygon.data();
00784
00785 bool inverted = orientation() == Qt::Vertical;
00786 if ( d_data->attributes & Inverted )
00787 inverted = !inverted;
00788
00789 const QwtSeriesData<QPointF> *series = data();
00790
00791 int i, ip;
00792 for ( i = from, ip = 0; i <= to; i++, ip += 2 )
00793 {
00794 const QPointF sample = series->sample( i );
00795 double xi = xMap.transform( sample.x() );
00796 double yi = yMap.transform( sample.y() );
00797 if ( doAlign )
00798 {
00799 xi = qRound( xi );
00800 yi = qRound( yi );
00801 }
00802
00803 if ( ip > 0 )
00804 {
00805 const QPointF &p0 = points[ip - 2];
00806 QPointF &p = points[ip - 1];
00807
00808 if ( inverted )
00809 {
00810 p.rx() = p0.x();
00811 p.ry() = yi;
00812 }
00813 else
00814 {
00815 p.rx() = xi;
00816 p.ry() = p0.y();
00817 }
00818 }
00819
00820 points[ip].rx() = xi;
00821 points[ip].ry() = yi;
00822 }
00823
00824 if ( d_data->paintAttributes & ClipPolygons )
00825 {
00826 QRectF clipRect = qwtIntersectedClipRect( canvasRect, painter );
00827
00828 const qreal pw = qMax( qreal( 1.0 ), painter->pen().widthF());
00829 clipRect = clipRect.adjusted(-pw, -pw, pw, pw);
00830
00831 const QPolygonF clipped = QwtClipper::clipPolygonF(
00832 clipRect, polygon, false );
00833
00834 QwtPainter::drawPolyline( painter, clipped );
00835 }
00836 else
00837 {
00838 QwtPainter::drawPolyline( painter, polygon );
00839 }
00840
00841 if ( d_data->brush.style() != Qt::NoBrush )
00842 fillCurve( painter, xMap, yMap, canvasRect, polygon );
00843 }
00844
00845
00854 void QwtPlotCurve::setCurveAttribute( CurveAttribute attribute, bool on )
00855 {
00856 if ( bool( d_data->attributes & attribute ) == on )
00857 return;
00858
00859 if ( on )
00860 d_data->attributes |= attribute;
00861 else
00862 d_data->attributes &= ~attribute;
00863
00864 itemChanged();
00865 }
00866
00871 bool QwtPlotCurve::testCurveAttribute( CurveAttribute attribute ) const
00872 {
00873 return d_data->attributes & attribute;
00874 }
00875
00893 void QwtPlotCurve::setCurveFitter( QwtCurveFitter *curveFitter )
00894 {
00895 delete d_data->curveFitter;
00896 d_data->curveFitter = curveFitter;
00897
00898 itemChanged();
00899 }
00900
00907 QwtCurveFitter *QwtPlotCurve::curveFitter() const
00908 {
00909 return d_data->curveFitter;
00910 }
00911
00924 void QwtPlotCurve::fillCurve( QPainter *painter,
00925 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00926 const QRectF &canvasRect, QPolygonF &polygon ) const
00927 {
00928 if ( d_data->brush.style() == Qt::NoBrush )
00929 return;
00930
00931 closePolyline( painter, xMap, yMap, polygon );
00932 if ( polygon.count() <= 2 )
00933 return;
00934
00935 QBrush brush = d_data->brush;
00936 if ( !brush.color().isValid() )
00937 brush.setColor( d_data->pen.color() );
00938
00939 if ( d_data->paintAttributes & ClipPolygons )
00940 {
00941 const QRectF clipRect = qwtIntersectedClipRect( canvasRect, painter );
00942 polygon = QwtClipper::clipPolygonF( clipRect, polygon, true );
00943 }
00944
00945 painter->save();
00946
00947 painter->setPen( Qt::NoPen );
00948 painter->setBrush( brush );
00949
00950 QwtPainter::drawPolygon( painter, polygon );
00951
00952 painter->restore();
00953 }
00954
00964 void QwtPlotCurve::closePolyline( QPainter *painter,
00965 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00966 QPolygonF &polygon ) const
00967 {
00968 if ( polygon.size() < 2 )
00969 return;
00970
00971 const bool doAlign = QwtPainter::roundingAlignment( painter );
00972
00973 double baseline = d_data->baseline;
00974
00975 if ( orientation() == Qt::Vertical )
00976 {
00977 if ( yMap.transformation() )
00978 baseline = yMap.transformation()->bounded( baseline );
00979
00980 double refY = yMap.transform( baseline );
00981 if ( doAlign )
00982 refY = qRound( refY );
00983
00984 polygon += QPointF( polygon.last().x(), refY );
00985 polygon += QPointF( polygon.first().x(), refY );
00986 }
00987 else
00988 {
00989 if ( xMap.transformation() )
00990 baseline = xMap.transformation()->bounded( baseline );
00991
00992 double refX = xMap.transform( baseline );
00993 if ( doAlign )
00994 refX = qRound( refX );
00995
00996 polygon += QPointF( refX, polygon.last().y() );
00997 polygon += QPointF( refX, polygon.first().y() );
00998 }
00999 }
01000
01014 void QwtPlotCurve::drawSymbols( QPainter *painter, const QwtSymbol &symbol,
01015 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
01016 const QRectF &canvasRect, int from, int to ) const
01017 {
01018 QwtPointMapper mapper;
01019 mapper.setFlag( QwtPointMapper::RoundPoints,
01020 QwtPainter::roundingAlignment( painter ) );
01021 mapper.setFlag( QwtPointMapper::WeedOutPoints,
01022 testPaintAttribute( QwtPlotCurve::FilterPoints ) );
01023
01024 const QRectF clipRect = qwtIntersectedClipRect( canvasRect, painter );
01025 mapper.setBoundingRect( clipRect );
01026
01027 const int chunkSize = 500;
01028
01029 for ( int i = from; i <= to; i += chunkSize )
01030 {
01031 const int n = qMin( chunkSize, to - i + 1 );
01032
01033 const QPolygonF points = mapper.toPointsF( xMap, yMap,
01034 data(), i, i + n - 1 );
01035
01036 if ( points.size() > 0 )
01037 symbol.drawSymbols( painter, points );
01038 }
01039 }
01040
01057 void QwtPlotCurve::setBaseline( double value )
01058 {
01059 if ( d_data->baseline != value )
01060 {
01061 d_data->baseline = value;
01062 itemChanged();
01063 }
01064 }
01065
01070 double QwtPlotCurve::baseline() const
01071 {
01072 return d_data->baseline;
01073 }
01074
01086 int QwtPlotCurve::closestPoint( const QPoint &pos, double *dist ) const
01087 {
01088 const size_t numSamples = dataSize();
01089
01090 if ( plot() == NULL || numSamples <= 0 )
01091 return -1;
01092
01093 const QwtSeriesData<QPointF> *series = data();
01094
01095 const QwtScaleMap xMap = plot()->canvasMap( xAxis() );
01096 const QwtScaleMap yMap = plot()->canvasMap( yAxis() );
01097
01098 int index = -1;
01099 double dmin = 1.0e10;
01100
01101 for ( uint i = 0; i < numSamples; i++ )
01102 {
01103 const QPointF sample = series->sample( i );
01104
01105 const double cx = xMap.transform( sample.x() ) - pos.x();
01106 const double cy = yMap.transform( sample.y() ) - pos.y();
01107
01108 const double f = qwtSqr( cx ) + qwtSqr( cy );
01109 if ( f < dmin )
01110 {
01111 index = i;
01112 dmin = f;
01113 }
01114 }
01115 if ( dist )
01116 *dist = qSqrt( dmin );
01117
01118 return index;
01119 }
01120
01130 QwtGraphic QwtPlotCurve::legendIcon( int index,
01131 const QSizeF &size ) const
01132 {
01133 Q_UNUSED( index );
01134
01135 if ( size.isEmpty() )
01136 return QwtGraphic();
01137
01138 QwtGraphic graphic;
01139 graphic.setDefaultSize( size );
01140 graphic.setRenderHint( QwtGraphic::RenderPensUnscaled, true );
01141
01142 QPainter painter( &graphic );
01143 painter.setRenderHint( QPainter::Antialiasing,
01144 testRenderHint( QwtPlotItem::RenderAntialiased ) );
01145
01146 if ( d_data->legendAttributes == 0 ||
01147 d_data->legendAttributes & QwtPlotCurve::LegendShowBrush )
01148 {
01149 QBrush brush = d_data->brush;
01150
01151 if ( brush.style() == Qt::NoBrush &&
01152 d_data->legendAttributes == 0 )
01153 {
01154 if ( style() != QwtPlotCurve::NoCurve )
01155 {
01156 brush = QBrush( pen().color() );
01157 }
01158 else if ( d_data->symbol &&
01159 ( d_data->symbol->style() != QwtSymbol::NoSymbol ) )
01160 {
01161 brush = QBrush( d_data->symbol->pen().color() );
01162 }
01163 }
01164
01165 if ( brush.style() != Qt::NoBrush )
01166 {
01167 QRectF r( 0, 0, size.width(), size.height() );
01168 painter.fillRect( r, brush );
01169 }
01170 }
01171
01172 if ( d_data->legendAttributes & QwtPlotCurve::LegendShowLine )
01173 {
01174 if ( pen() != Qt::NoPen )
01175 {
01176 QPen pn = pen();
01177 pn.setCapStyle( Qt::FlatCap );
01178
01179 painter.setPen( pn );
01180
01181 const double y = 0.5 * size.height();
01182 QwtPainter::drawLine( &painter, 0.0, y, size.width(), y );
01183 }
01184 }
01185
01186 if ( d_data->legendAttributes & QwtPlotCurve::LegendShowSymbol )
01187 {
01188 if ( d_data->symbol )
01189 {
01190 QRectF r( 0, 0, size.width(), size.height() );
01191 d_data->symbol->drawSymbol( &painter, r );
01192 }
01193 }
01194
01195 return graphic;
01196 }
01197
01205 void QwtPlotCurve::setSamples( const QVector<QPointF> &samples )
01206 {
01207 setData( new QwtPointSeriesData( samples ) );
01208 }
01209
01220 void QwtPlotCurve::setSamples( QwtSeriesData<QPointF> *data )
01221 {
01222 setData( data );
01223 }
01224
01225 #ifndef QWT_NO_COMPAT
01226
01241 void QwtPlotCurve::setRawSamples(
01242 const double *xData, const double *yData, int size )
01243 {
01244 setData( new QwtCPointerData( xData, yData, size ) );
01245 }
01246
01258 void QwtPlotCurve::setSamples(
01259 const double *xData, const double *yData, int size )
01260 {
01261 setData( new QwtPointArrayData( xData, yData, size ) );
01262 }
01263
01272 void QwtPlotCurve::setSamples( const QVector<double> &xData,
01273 const QVector<double> &yData )
01274 {
01275 setData( new QwtPointArrayData( xData, yData ) );
01276 }
01277
01278 #endif // !QWT_NO_COMPAT
01279